MyBatis框架下防止SQL注入

与传统的ORM框架不同,MyBatis使用XML描述符将对象映射到SQL语句或者存储过程中,这种机制可以让我们更大的灵活度通过SQL来操作数据库对象,因此,我们必须小心这种便利下SQL注入的可能性。

安全用法

<select id="getPerson" parameterType="int" resultType="org.application.vo.Person">
SELECT * FROM PERSON WHERE ID = #{id}
</select>

这是我们推荐的一种用法,注意参数符号#{id},使用#{}语法,MyBatis会通过预编译机制生成PreparedStatement参数,然后在安全的给参数进行赋值操作,因此就避免了SQL注入:

/* Comparable JDBC code */
String selectPerson = "SELECT * FROM PERSON WHERE ID = ?"; 
PreparedStatement ps = conn.prepareStatement(selectPerson); 
ps.setInt(1, id);

更多安全用法示例:

<insert id="insertPerson" parameterType="org.application.vo.Person">
insert into Person (id, name, email, phone)
values (#{id}, #{name}, #{email}, #{phone})
</insert>
 
<update id="updatePerson" parameterType="org.application.vo.Person">
update Person set name = #{name}, email = #{email}, phone = #{phone}
where id = #{id}
</update>
 
 
<delete id="deletePerson" parameterType="int">
delete from Person where id = #{id}
</delete>

不安全用法

<select id="getPerson" parameterType="string" resultType="org.application.vo.Person">
SELECT * FROM PERSON WHERE NAME = #{name} AND PHONE LIKE '${phone}'; 
</select>

首先,这是一种不全的用法,注意上面的参数修符号${phone} ,使用${}参数占位修饰符,MyBatis不会对字符串做任何修改,而是直接插入到SQL语句中。这也就是说MyBatis在对参数进行替换操作时,不会对参数值进行任何修改或者转义操作。

假设,电话号码phone参数由用户进行输入,系统本身未对输入值进行任何校验或者转义,那么潜在攻击者可能通过输入类似:"1%' OR '1'='1"这样的电话号码值,那么用户查询语句就会变成下面的格式:

SELECT * FROM PERSON WHERE NAME = ? and PHONE LIKE '1%' OR '1' = '1'

另外,如果电话号码是这样的值:A%'; DELETE FROM PERSON; --,脚本执行的结果可能就是删除 PERSON 表中的所有记录:

SELECT * FROM PERSON WHERE NAME = ? and PHONE LIKE 'A%'; DELETE FROM PERSON; --'

像上面这种用法,后台直接接收用户输入,而不对输入进行任何校验都是非常危险的,这可能带来潜在的SQL注入攻击,因此,当我们在使用${}语法时,接受参数应不允许用户输入,或者允许用户输入,系统必须对用户输入进行必要的校验和转义。

下面是一些不安全的用法示例

<insert id="insertPerson" parameterType="org.application.vo.Person">
insert into Person (id, name, email, phone)
values (#{id}, #{name}, #{email}, ${phone})
</insert>
 
<update id="updatePerson" parameterType="org.application.vo.Person">
update Person set phone = ${phone}
where id = #{id}
</update>
 
 
<delete id="deletePerson" parameterType="int">
delete from Person where id = ${id}
</delete>

原文链接:
https://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-mybatis

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章