Mybatis 的 Mapper.xml 語句中 parameterType 向SQL語句傳參有兩種方式:\ { } 和 ${ }。 使用\ { }是來防止SQL註入,使用${ }是用來動態拼接參數。 如何排查出 1. 檢查是否有\$號 如果你使用的是ide代碼編輯器,那麼可以通過全局搜索 , 快速 ...
Mybatis 的 Mapper.xml 語句中 parameterType 向SQL語句傳參有兩種方式:#{ } 和 ${ }。
使用#{ }是來防止SQL註入,使用${ }是用來動態拼接參數。
如何排查出
1. 檢查是否有$號
如果你使用的是ide代碼編輯器,那麼可以通過全局搜索${
, 快速定位到使用${ }拼接SQL的語句,在去找到外部傳入參數的入口,閉合sql證明即可。
2. 檢查是否有order by語句
同樣的在搜索是否使用order by
排序語句,如果有一步一步追蹤是否有外部參數,未過濾就直接傳遞到order by語句裡面來。
為什麼#{ }就安全
#{ } 就類似JDBC的預編譯,所以安全。類似如下SQL語句:(JDBC預編譯的原理,希望後面能專門去研究一下,並寫博文)
- 使用 ${ }效果是:
select * from testtable where id="1" or true or id # 1後面就是被攻擊者惡意構造的字元
- 而使用#{ } 的效果是:
select * from testtable where id="1\" or true or id\"" # 1後面就是被攻擊者惡意構造的字元
什麼情況下用不了#{}
答案是:在order by 排序語句的情況下不行,為什麼?
先複習一下order by的用法
order by就是一個排序的工具。
# 這個1就是指第一個列索引,也可以寫id (列索引)
select * from testtable ORDER BY 1 ASC #ASC表示按升序排序,DESC表示按降序排序
# 兩個代碼是一樣的
select * from testtable ORDER BY id ASC #ASC表示按升序排序,DESC表示按降序排序
對於order by 我們是用不了#{}的,因為用了這個就會被自動轉換成字元串,自動加引號,這樣語句就不生效了。
<select id="selectStudentsByName" resultType="Student">
select id,name,age,score from student order by #{column}
</select>
<!--編譯出來的結果如下:-->
select * from table order by 'column'
會發現加上“”
雙引號符號後,就沒法正常排序了。
如何解決:
使用${},MyBatis就不會修改或轉義改字元串。但是這樣又不安全,會導致潛在的SQL註入攻擊。所以我們需要自己去限制,不允許用戶輸入一些非法欄位,通常只使用白名單方式校驗。
總結
即使是安全的sql預編譯技術,也是有適用範圍的,一些應用場景也是不適用的。當我們在做黑盒或者審計的時候,碰到了預編譯處理不了的場景,比如說排序功能的時候就得格外註意了,不然被人order by
註入就悲劇了。