背景:
某一天准備上線,合完master之后准備發布了,忽然公司的代碼安全監測提示了可能在代碼中存在sql注入的風險,遂即檢查,發現sql注入問題
既然碰到了這個問題,那就了簡單了解下sql注入
基礎知識:
SQL注入基本原理:
所謂SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。
注入攻擊的本質,是把用戶輸入的數據當做代碼執行。這里有兩個關鍵條件,第一個是用戶能夠控制輸入;第二個是原本程序要執行的代碼,拼接了用戶輸入的數據。
SQL注入類型
按照注入點類型來分類
(1).數字型注入點(當輸入的參數為整形時,如果存在注入漏洞,可以認為是數字型注入。)
sql原型: select * from aaa where id = 1 ,有如下種可能:
1). 加單引號,對應的sql: select * from aaa where id=3’ 這時sql語句出錯,程序無法正常從數據庫中查詢出數據,就會拋出異常;
2).加or 1=1,對應的sql: select*from aaa where id=3 or 1=1 這個時候能夠查詢到所有的結果
3).加上 and 1=1 對應的sql:select * from aaa where id=3 and 1=1 不能查詢到結果
(2).字符型注入點(當輸入的參數為字符串時,稱為字符型。字符型和數字型最大的一個區別在於,數字型不需要單引號來閉合,而字符串一般需要通過單引號來閉合的。)
sql原型: select * from aaa where name='admin' ,有如下種可能:
1).加單引號:
select * from aaa where name ='admin' and 1=1 -- '
這種注入方式並不會影響查詢結果
2).加union:
select name from aaa where name='1' union select database()#'
這種的結果就是把數據庫信息泄露出去。
3).加or
select name from aaa where name='11' or '1234 '='1234'
這種就是導致查詢的結果並不是期望的結果,導致數據泄露
(3).搜索型注入點(說明一下,搜索型注入也無他,前加%' 后加 and '%'=' 對於MYSQL數據庫,后面可以吧 and '%'='換成--)
這是一類特殊的注入類型。這類注入主要是指在進行數據搜索時沒過濾搜索參數,一般在鏈接地址中有“keyword=關鍵字”,有的不顯示在的鏈接地址里面,而是直接通過搜索框表單提交。此類注入點提交的 SQL 語句,其原形大致為:select * from 表名 where 字段 like '%關鍵字%'
。
按照數據提交的方式來分類
(1)GET 注入
提交數據的方式是 GET , 注入點的位置在 GET 參數部分。比如有這樣的一個鏈接http://xxx.com/news.php?id=1
, id 是注入點。
(2)POST 注入
使用 POST 方式提交數據,注入點位置在 POST 數據部分,常發生在表單中。
(3)Cookie 注入
HTTP 請求的時候會帶上客戶端的 Cookie, 注入點存在 Cookie 當中的某個字段中。
(4)HTTP 頭部注入
注入點在 HTTP 請求頭部的某個字段中。比如存在 User-Agent 字段中。嚴格講的話,Cookie 其實應該也是算頭部注入的一種形式。因為在 HTTP 請求的時候,Cookie 是頭部的一個字段。
按照執行效果來分類
(1)基於布爾的盲注,即可以根據返回頁面判斷條件真假的注入。
(2)基於時間的盲注,即不能根據頁面返回內容判斷任何信息,用條件語句查看時間延遲語句是否執行(即頁面返回時間是否增加)來判斷。
(3)基於報錯注入,即頁面會返回錯誤信息,或者把注入的語句的結果直接返回在頁面中。
(4)聯合查詢注入,可以使用union的情況下的注入。
(5)堆查詢注入,可以同時執行多條語句的執行時的注入。
基本原理了解了一些之后,再來一個案例吧
案例:
持久層框架:MyBatis
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.1</version> </dependency>
sql內容:
<if test="query.orderBy != null"> ORDER BY ${query.orderBy} </if>
背景:orderBy使用不規范也會引發sql注入嗎?
例如:
select * from aaa order by id and(updatexml(1,concat(0x7e,(select system_user())),0));
這里介紹下:UPDATEXML (XML_document, XPath_string, new_value);
第一個參數:XML_document是String格式,為XML文檔對象的名稱,文中為Doc
第二個參數:XPath_string (Xpath格式的字符串) (XPATH格式:http://www.cnblogs.com/Loofah/archive/2012/05/10/2494036.html)
第三個參數:new_value,String格式,替換查找到的符合條件的數據
作用:改變文檔中符合條件的節點的值
執行上面的sql,通過報錯內容獲取當前連接數據庫的用戶名
[SQL]select * from aaa order by id and(updatexml(1,concat(0x7e,(select system_user())),0)); [Err] 1105 - XPATH syntax error: '~root@localhost'
在mybatis中如何避免?
在mybatis中,#{} 相當於 jdbc中的preparedstatement,就是說傳遞過來的參數會自動加上單引號,而${} 是直接輸出變量的值。一般來說,使用#{}語法,MyBatis會產生PreparedStatement語句中,並且安全的設置PreparedStatement參數,這個過程中MyBatis會進行必要的安全檢查和轉義。比如這樣:
執行SQL:Select * from aaa where name = #{name} 參數:aaa 解析后執行的SQL:Select * from aaa where name = ?
也就是說#{}更安全一些。但是order by 明顯是不能使用這種方式的。order by 之后如果使用 #{} 使用時則變成了 order by '...' 那么sql就直接報錯了
避免該種類型的sql注入的有效措施就是在程序中判斷排序字段 以保證xml中只可能出現某些情況或者在xml中固定排序字段
- 模糊查詢 like
正常程序: select * from aaa where name like '%${likeColumn}%' 可能會存在sql注入問題
修改后:
select * from aaa where name like concat('%',#{likeColumn},'%')
修改點:從 ${} 改為 #{},從sql拼接到 concat方式
- in之后的參數
正常程序: Select * from aaa where id in (${id})
修改后:
select * from aaa where id in <foreach collection="ids" item="item" open="("separator="," close=")">#{item} </foreach>
ok,先簡單對sql注入有個了解。
https://blog.csdn.net/m0_37438418/article/details/80260813 一道綜合滲透題引發的updatexml()注入思考
https://www.cnblogs.com/moxiaotao/p/9330711.html Java框架之MybatisSQL注入漏洞
https://www.cnblogs.com/xuthus/p/9450805.html SQL注入 (1) SQL注入類型介紹
https://blog.csdn.net/qq_30464257/article/details/84495884 如何判斷是字符型注入還是整形注入
http://www.hackdig.com/?08/hack-5209.htm