1. 程式人生 > >Mybatis框架下SQL注入漏洞處理

Mybatis框架下SQL注入漏洞處理

來源:http://www.open-open.com/lib/view/open1474963603800.html

           http://mp.weixin.qq.com/s?__biz=MjM5OTk2MTMxOQ==&mid=2727827368&idx=1&sn=765d0835f0069b5145523c31e8229850&mpshare=1&scene=1&srcid=0926iDLkz6CKTO9IUh5fqt3o#rd

一、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 * from news where id in

<foreach collection="ids" item="item" open="("separator="," close=")">#{item} </foreach>

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)。