审计mybatis的SQL注入
Posted MottoIN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了审计mybatis的SQL注入相关的知识,希望对你有一定的参考价值。
mybatis 概述
MyBatis(www.mybatis.org)是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录
mybatis存在的sql注入问题
mybatis避免了用户直接拼接SQL语句,但是认为只要使用了mybatis就可以杜绝SQL注入的观点是不正确的。
mybatis在配置SQL语句的时候,有两种描述参数的方式。#{}和${}。
比如:
这个语句被称作 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap类型的对象,其中的键是列名,值便是结果行中的对应值。
注意参数符号:
#{id}
这就告诉 MyBatis 创建一个预处理语句参数,通过 JDBC,这样的一个参数在 SQL中会由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:
使用#mybatis会使用预编译来处理参数,这样子可以避免SQL注入。
但是使用$描述参数会直接把变量拼接到SQL语句中,不做任何处理。相当于直接字符串拼接SQL。这样的方式就可能存在SQL注入。下面的描述来自mybatis官方文档。
默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值(比如?)。这样做更安全,更迅速,通常也是首选做法,不过有时你只是想直接在 SQL 语句中插入一个不改变的字符串。比如,像 ORDER BY,你可以这样来使用: ORDER BY ${columnName} 这里 MyBatis 不会修改或转义字符串。 NOTE 以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。
demo演示
使用MyBatis使用示例作为demo测试。
mapper文件:
在输入中插入单引号
查看执行的sql语句:
可以看到输入被单引号包裹,并且对字符串中的单引号进行了转义。
将#改成$,mapper文件为:
这里由于代码的写法问题,name需要改成_parameter,参考Mybatis中传参包There is no getter for property named XXX in class java.lang.String:http://woshixy.blog.51cto.com/5637578/1180914。
查看执行的SQL语句:
输入没有任何改变的拼接到SQL中,造成了SQL注入。
实战分析
mybatis generator插件默认生成的order by 条件是使用$表示变量。
前面的分析可以知道,这种情况,mybatis会直接拼接字符串到SQL中不做任何处理。
注册用户登录访问:
http://192.168.99.100:8080/freecms/member/creditlog_list.do?order=extractvalue(1,concat(0x7C,(select%20user()),0x7C))
查看执行的SQL为:
修复方案
尽量使用#描述参数,如果一定要使用$,则需要自己过滤用户输入。
以上是关于审计mybatis的SQL注入的主要内容,如果未能解决你的问题,请参考以下文章