與傳統的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