什么是 SQL 注入,這些坑得避開(kāi)
1、sql 注入是什么
sql 注入就是用戶通過(guò)輸入的參數(shù),拼接到原先的 sql 中,成為 sql 的一部分,從而影響 sql 的功能和執(zhí)行結(jié)果
2、sql 注入破壞力
-小兵破壞力
比如原先 sql 如下
- select * from user where name='用戶名' and password='密碼';
用戶輸入
- name:臻大蝦'-- '注釋
- password:密碼
那最終的結(jié)果猜猜是什么?
- select * from user where name='臻大蝦'-- '注釋' and password='密碼';
兩個(gè)-- 代表注釋,所以這條 sql 只需要輸入用戶名,就可以獲取用戶信息,跳過(guò)了密碼的校驗(yàn)
-boss 破壞力
來(lái)個(gè)厲害的,比如用戶輸入以下參數(shù)
- name:臻大蝦
- password:'; drop table user;-- '注釋
最終的 sql:
- select * from user where name='臻大蝦' and password=''; drop table user;-- '注釋';
user 表居然被刪除了,看到這,此時(shí)的你可能想原地爆炸。
3、對(duì)策
3.1、PreparedStatement 預(yù)編譯
使用預(yù)編譯,這樣傳入的參數(shù),會(huì)被當(dāng)作字符串,也就是被引號(hào)包起來(lái)
拿剛才的例子,用戶輸入
- name:臻大蝦'-- '注釋
- password:密碼
如果使用了預(yù)編譯,那最終的 sql
- select * from user where name='臻大蝦\'-- \'注釋' and password='密碼';
參數(shù)中的引號(hào)被轉(zhuǎn)義,從而避免成為 sql 的一部分。
3.2、有些語(yǔ)句不能預(yù)編譯
預(yù)編譯獲取參數(shù)是根據(jù)#,而$ 是拼接的意思
#{}:解析為預(yù)編譯語(yǔ)句的一個(gè)參數(shù)占位符
${}:僅僅作為一個(gè)字符串,在動(dòng)態(tài) sql 中直接替換變量,傳入什么值,就是什么值
比如傳入:'臻大蝦' or 1=1
- 1、SELECT * FROM user WHERE name=#{name} //SELECT * FROM user WHERE name='\'臻大蝦\' or 1=1'
- 2、SELECT * FROM user WHERE name=${name} //SELECT * FROM user WHERE name='臻大蝦' or 1=1
但是有些情況使用#會(huì)報(bào)錯(cuò),比如 like、in 如果使用#會(huì)報(bào)錯(cuò),而使用
還有 order by,根據(jù)傳入的參數(shù)排序,這些情況就會(huì)有 sql 注入的危險(xiǎn),那怎么辦呢?
-
like
- select * from user where name like '%#{name}%' //會(huì)報(bào)錯(cuò)
- select * from user where name like '%${name}%' //正常
正確寫(xiě)法
使用 mysql 的字符串拼接函數(shù) concat
- select * from user where name like concat('%',#{name},'%')
-
in
正確寫(xiě)法,使用 foreach
- @Select("<script>" +
- "select * from user where id in "+
- "<foreach item='item' index='index' collection='userIds' open='(' separator=',' close=')'> " +
- "#{item}" +
- "</foreach>"+
- "</script>")
- List<User> getByIds(@Param("userIds") List<Long> userIds);
-
order by
有時(shí)需要根據(jù)前端傳入的參數(shù)來(lái)排序,此時(shí)就會(huì)有 sql 注入的危險(xiǎn),此時(shí)可以使用白名單
比如
- List<String> allowSortColumnList= Lists.newArrayList("age","score");
- if(!allowSortColumnList.contains(sortParam)){
- throw new RuntimeException("can not sort by "+sortParam);
- }