前言
在java中,最常見的連接數據庫方式有JDBC,Mybatis,和Hibernate。那我們只需要注意這些地方就可以判斷是否存在sql注入即可
0x01、Mybatis下SQL注入
Mybatis的SQL語句可以基於注解的方式寫在類方法上面,更多的是以xml的方式寫到xml文件。Mybatis中SQL語句需要我們自己手動編寫或者用generator自動生成。
編寫xml文件時,Mybatis支持兩種參數符號,一種是#,另一種是$。比如:
<select id="queryAll" resultMap="resultMap">
SELECT * FROM NEWS WHERE ID = #{id}
</select>
而java開發的站點中大部分是預編譯,也就是說存在的sql注入少了;但是,還是有些語句不能進行預編譯,從而導致sql注入。為什么呢?因為預編譯中獲取參數從而執行sql語句使用的#
號,然而$
符是拼接的意思,像like,in這種使用不規范#符就會報錯,所以就會使用$。那么這種就一定的幾率存在注入,一切看開發是新手還是老司機
導入依賴
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatis的依賴-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
1、like模糊查詢注入
Select * from news where title like '%#{title}%' //報錯
Select * from news where title like '%${title}%' //正常
在這種情況下使用#程序會報錯,新手程序員就把#號改成了$,這樣如果java代碼層面沒有對用戶輸入的內容做處理勢必會產生SQL注入漏洞。
正確寫法:
select * from news where tile like concat(‘%’,#{title}, ‘%’)
2、in 注入
in之后多個id查詢時使用# 同樣會報錯,
Select * from news where id in (#{id}) //報錯
Select * from news where id in (${id}) //正常
正確用法為使用foreach,而不是將#替換為$
id in
<foreach collection="id" item="item" open="("separatosr="," close=")">
#{id}
</foreach>
3、order by 注入
這種場景應當在Java層面做映射,設置一個字段/表名數組,僅允許用戶傳入索引值。這樣保證傳入的字段或者表名都在白名單里面。需要注意的是在mybatis-generator自動生成的SQL語句中,order by使用的也是$,而like和in沒有問題。
Select * from news where title ='#{titlename}' order by #{time} asc //報錯
Select * from news where title ='#{titlename}' order by ${time} asc //正常
總結
總的來說,其實是新手程序員,因為使用#會報錯,從而發現$符不會報錯,進行使用$符;但是本身程序員自己不會用而導致的
java sql注入問題適合使用反推,先搜索xml查找可能存在注入的漏洞點→反推到DAO→再到實現類→再通過調用鏈找到前台URL,找到利用點