Sql注入之mybatis框架

一、SQL注入漏洞基本原理
在常見的web漏洞中,SQL注入漏洞較爲常見,危害也較大。攻擊者一旦利用系統中存在的SQL注入漏洞來發起攻擊,在條件允許的情況下,不僅可以獲取整站數據,還可通過進一步的滲透來獲取服務器權限,從而進入內網。
注入攻擊的本質,是把用戶輸入的數據當做代碼執行。這裏有兩個關鍵條件,第一個是用戶能夠控制輸入;第二個是原本程序要執行的代碼,拼接了用戶輸入的數據。接下來說下SQL注入漏洞的原理。
舉個例子。當用戶發送GET請求:http://www.xxx.com/news.jsp?id=1這是一個新聞詳情頁面,會顯示出新聞的title和content,程序內部會接收這個id參數傳遞給SQL語句,SQL如下:SELECT title,content FROM news WHERE id = 1
這是SQL的原義,也是程序員想要得到的結果,但是如果用戶改變了id的內容,修改成如下:http://www.jd.com/news.jsp?id=1 and 1=2 UNION SELECT userna-me, password FROM admin此時內部程序執行的SQL語句爲:SELECT title,content FROM news WHERE id = 1 and 1=2 UNION SELECT username, password FROM admin
這條SQL的原義就會被改變,導致將管理員數據表中的用戶名顯示在頁面title位置,密碼顯示在頁面content位置,攻擊成功。

二、Mybatis框架介紹
1. Mybatis框架架構
Mybatis框架架構講解(架構圖如下圖所示):
(1)加載配置:配置來源於兩個地方,一處是配置文件,一處是Java代碼的註解,將SQL的配置信息加載成爲一個個MappedStatement對象(包括了傳入參數映射配置、執行的SQL語句、結果映射配置),存儲在內存中。
(2) SQL解析:當API接口層接收到調用請求時,會接收到傳入SQL的ID和傳入對象(可以是Map、JavaBean或者基本數據類型),Mybatis會根據SQL的ID找到對應的MappedStatement,然後根據傳入參數對象對MappedStatement進行解析,解析後可以得到最終要執行的SQL語句和參數。
(3)SQL執行:將最終得到的SQL和參數拿到數據庫進行執行,得到操作數據庫的結果。
(4)結果映射:將操作數據庫的結果按照映射的配置進行轉換,可以轉換成HashMap、JavaBean或者基本數據類型,並將最終結果返回。
Mybatis架構圖
2. JDBC預編譯模式
Mybatis框架作爲一款半自動化的持久層框架,其SQL語句都需要我們自己手動編寫,此時就需要按照安全編碼規範進行開發,以防止SQL注入漏洞的產生。
針對上一節中所舉的例子,應用Mybatis框架SQL語句安全寫法(即JDBC預編譯模式)可以寫爲:
select * from news where id=#{id},這種寫法可以很好地避免SQL注入漏洞的產生。
3. 動態拼接SQL語句
如果在開發過程中沒有采用JDBC的預編譯模式,如我們將上述SQL語句寫爲:select * from news where id=${id},這種寫法就產生了SQL語句的動態拼接。因爲”${xxx}”這樣格式的參數會直接參與SQL語句的編譯,從而不能避免SQL注入攻擊。

三、Mybatis框架下易產生SQL注入漏洞場景分析
在基於Mybatis框架的Java白盒代碼審計工作中,通常將着手點定位在Mybatis的配置文件中。通過查看這些與數據庫交互的配置文件來確定SQL語句中是否存在拼接情況,進而確立跟蹤點。通過總結,Mybatis框架下易產生SQL注入漏洞的情況主要分爲以下三種:
1. 模糊查詢like
還以第一節中提到的新聞詳情頁面爲例,按照新聞標題對新聞進行模糊查詢,如果考慮安全編碼規範問題,其對應的SQL語句如下:
Select * from news where title like ‘%#{title}%’,
但由於這樣寫程序會報錯,研發人員將SQL查詢語句修改如下:
Select * from news where title like ‘%${title}%’,
在這種情況下我們發現程序不再報錯,但是此時產生了SQL語句拼接問題,如果java代碼層面沒有對用戶輸入的內容做處理勢必會產生SQL注入漏洞。
2. in之後的參數
在對新聞進行同條件多值查詢的時候,如當用戶輸入1001,1002,1003…100N時,如果考慮安全編碼規範問題,其對應的SQL語句如下:
Select * from news where id in (#{id}),
但由於這樣寫程序會報錯,研發人員將SQL查詢語句修改如下:
Select * from news where id in (${id}),
修改SQL語句之後,程序停止報錯,但是卻引入了SQL語句拼接的問題,如果研發人員沒有對用戶輸入的內容做過濾,勢必會產生SQL注入漏洞。
3. order by之後
當根據發佈時間、點擊量等信息對新聞進行排序的時候,如果考慮安全編碼規範問題,其對應的SQL語句如下:
Select * from news where title =‘京東’ order by #{time} asc,
但由於發佈時間time不是用戶輸入的參數,無法使用預編譯。研發人員將SQL查詢語句修改如下:
Select * from news where title =‘京東’ order by ${time} asc,
修改之後,程序通過預編譯,但是產生了SQL語句拼接問題,極有可能引發SQL注入漏洞。

四、Mybatis框架下SQL注入漏洞修復建議1. 模糊查詢like SQL注入修復建議
按照新聞標題對新聞進行模糊查詢,可將SQL查詢語句設計如下:
select * from news where tile like concat(‘%’,#{title}, ‘%’),
採用預編譯機制,避免了SQL語句拼接的問題,從根源上防止了SQL注入漏洞的產生。
2.  in之後的參數SQL注入修復建議
在對新聞進行同條件多值查詢的時候,可使用Mybatis自帶循環指令解決SQL語句動態拼接的問題:
<select id="dynamicForeachTest" parameterType="java.util.List" resultType="Blog">
   select * from t_blog where id in 
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> 
       #{item} 
    </foreach> 
</select>
3. order by SQL注入修復建議--在Java層面做映射
預編譯機制只能處理查詢參數,其他地方還需要研發人員根據具體情況來解決。如前面提到的排序情景: Select * from news where title =‘京東’ order by #{time} asc,這裏time不是查詢參數,無法使用預編譯機制,只能這樣拼接:Select * from news where title =‘京東’ order by ${time} asc 。
針對這種情況研發人員可以在java層面做映射來進行解決。如當存在發佈時間time和點擊量click兩種排序選擇時,我們可以限制用戶只能輸入1和2。當用戶輸入1時,我們在代碼層面將其映射爲time,當用戶輸入2時,將其映射爲click。而當用戶輸入1和2之外的其他內容時,我們可以將其轉換爲默認排序選擇time(或者click)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章