前言:最近在學Mybatis,趁機把Mybatis框架下可能引發的SQL注入來過一遍,加深理解
Mybatis傳遞數據有兩種方式,一種是#{},還有一種是${},而#{}基本能防止SQL注入,但是某些環境下需要用到${},所以可能就會導致SQL注入的產生
大概產生SQL注入的有如下幾種類型,自己都會詳細的記錄,以及自己的思考
1、模糊查詢like
2、in之后的參數
3、order by
數據表userinfo的數據如下:

模糊查詢like
Mapping.xml
<!--like下的SQL注入-->
<select id="getUserByName" parameterType="String" resultType="com.zpchcbd.pojo.User">
select * from userinfo where name like "%"#{name}"%"
</select>
業務代碼:
public static void test06(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserByName("六");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
首先一開始想要實現先試試如下
select * from userinfo where name like '%#{name}%'

發現會報錯,它根本識別不了索引值來進行替換

那么如果將SQL語句改成如下為,發現能正常的查詢出數據!
select * from userinfo where name like '%${name}%'

發現用${}來執行的SQL語句,最終的SQL語句為如下,也就是只是單純的替換了,連預編譯的工作都沒有進行處理!
select * from userinfo where name like '%六%'
如果我們此時加一個單引號則會出現報錯!

到目前則證明了如果使用${},則是使用拼接SQL語句的方法,那么就會造成SQL注入,但是如果想要預防SQL注入試圖通過#{}來寫,又會發生報錯!
所以對於模糊查詢like的SQL注入就是這樣子產生的,一般人就會使用${}來進行查詢,修復方法就是自己還需要手動加一層過濾才行
自己又想了下那么如果SQL語句是這樣呢?select * from userinfo where name like "%"#{name}"%"

發現它是可以查詢的,並且會進行預編譯操作,最終的SQL語句為如下:select * from userinfo where name like "%"'六'"%";,這種自己沒見過,猜想是不是在mysql中可能就是單引號和雙引號會自動進行拼接?那這種可以作為一種繞過方法嗎?還需要去研究或者有懂的人可以告知下!

到這里,我們其實就可以明白了${} #{} 本質到底做了什么事,${}這個東西就是我們正常在寫SQL語句中的進行拼接的操作,這種是十分可能引起SQL注入的,然而#{}則是經過預編譯的操作,其實也就是一個占位符?,預編譯會自動給你兩邊加上單引號,並且對其中的非法字符進行轉義操作,最終預防了SQL注入的產生!
但是一旦跟業務掛鈎之后,SQL注入就十分容易的產生!
in之后的參數
繼續來in的SQL注入
Mapper.xml
<select id="getUserById" resultType="com.zpchcbd.pojo.User">
select * from userinfo where id in (${id})
</select>
// getuser by id
public static void test02(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserById("1,2,3");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
先是傳遞"1,2,3",發現在#{}的情況下也可以正常查詢,但是只能查詢到一條,原因同樣是預編譯的影響,最終的SQL語句為select * from userinfo where id in ('1,2,3')

當改成${}的時候,則最終查詢的記錄為3條,SQL語句為:select * from userinfo where id in (1,2,3)


所以才會導致SQL注入的產生,其實都是跟業務掛鈎
order by
參考之前寫過的:https://www.cnblogs.com/zpchcbd/p/14725943.html
官方文檔對${}和#{}的介紹:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

