SQL注入測試
0x01 等保測評項
GBT 22239-2019《信息安全技術 網絡安全等級保護基本要求》中,8.1.4.4安全計算環境—入侵防范項中要求包括:
a)應遵循最小安裝的原則,僅安裝需要的組件和應用程序;
b)應關閉不需要的系統服務、默認共享和高危端口;
c)應通過設定終端接入方式或網絡地址范圍對通過網絡進行管理的管理終端進行限制;
d)應提供數據有效性檢驗功能,保證通過人機接口輸入或通過通信接口輸入的內容符合系統設定要求;
e)應能發現可能存在的已知漏洞,并在經過充分測試評估后,及時修補漏洞;
f)應能夠檢測到對重要節點進行入侵的行為,并在發生嚴重入侵事件時提供報警。
SQL注入測試對應訪問控制項中要求d),所以安全控制點為入侵防范d。
GBT 28448-2019《信息安全技術 網絡安全等級保護測評要求》中,測評單元(L3-CES1-20),該項測評單元包括以下要求:
a)測評指標:應提供數據有效性檢驗功能,保證通過人機接口輸入或通過通信接口輸入的內容符合系統設定要求。
b)測評對象:業務應用系統、中間件和系統管理軟件及系統設計文檔等。
c)測評實施包括以下內容:
1)應核查系統設計文檔的內容是否包括數據有效性檢驗功能的內容或者模塊;
2)應測試驗證是否對人機接口或通信接口輸入的內容進行有效性檢驗。
d)單元判定:如果1)和2)均為肯定,則符合本測評單元指標要求,否則不符合或部分符合本測評單元指標要求。
SQL注入測試屬于測評單元(L3-CES1-20)中測評實施第2項,故測評單元為L3-CES1-20.2。
0x02 測試內容
通過手工或工具的方式,檢測系統是否存在SQL注入漏洞,是否能通過SQL注入查詢相關敏感信息或執行命令、獲取權限等操作。
0x03 漏洞原理
WEB應用程序對用戶輸入的數據沒有進行合法性判斷,前端傳入后端的參數是攻擊者可控的,并且能將參數帶入數據庫中查詢,攻擊者就可以通過構造不同的SQL語句實現對數據庫的任意操作。
SQL注入漏洞的產生需要滿足兩個條件:
- 參數用戶可控:前端傳給后端的參數內容是用戶可以控制的;
- 參數帶入數據庫查詢:傳入的參數拼接到SQL語句中,且帶入數據庫查詢;
在實際環境中,凡是滿足上述兩個條件的參數皆可能存在SQL注入漏洞,因此開發者需秉持“外部參數皆不可信的原則”進行應用程序的開發。
0x04 代碼示例

上述代碼,程序獲取GET參數id,對用戶傳過來的id值沒有進行過濾,直接拼接到SQL語句中,在數據庫中查詢id對應的內容,并將這一條查詢結果中的user和password 輸出到頁面。就可以進行常規的union注入。
0x05 限制繞過
WEB應用程序通常會使用輸入過濾器,設計這些過濾器的目的是防御包括SQL注入內的常見攻擊。這些過濾器可能位于應用的代碼中(自定義輸入驗證方式),也可能在應用外部實現,形式為WEB應用防火墻(WAF)或入侵防御系統(IPS)。
我們還有可能遇到嘗試將輸入修改為安全內容的過濾器,這些過濾器使用的方法包括編碼、消除有問題的字符或者從輸入中剝去帶有攻擊性的項并按正常方式處理余下內容。
通常,由這些過濾器保護的應用程序代碼易受到SQL注入的攻擊。如果想要利用漏洞,就需要尋找一種避開過濾器的方法以便將惡意輸入傳遞給易受攻擊的代碼。

繞過方式:
注釋符
當過濾器阻止各種空白符常見關鍵詞過濾時,可使用注釋進行繞過
-- “注釋內容” /*注釋內容*/ ;
內聯注釋
內聯注釋能把一些特有的僅在MYSQL上的語句放在 /!../ 中,這樣這些語句如果在其它數據庫中是不會被執行,但在MYSQL的特定版本(與注釋內描述的版本有關)中會執行。
select * from cms_users where userid=1 union /*!5000 select*/ 1,2,3;
編碼
瀏覽器中輸入的URL會由瀏覽器進行一次URL編碼,所以可以通過多次編碼繞過正則表達式的檢測;如URLEncode編碼、ASCII、HEX、unicode編碼繞過:
對關鍵字進行兩次url全編碼: 1+and+1=2 1+%25%36%31%25%36%65%25%36%34+1=2 /**/union/**/select/**/password/**/from/**/users/**/where/**/username/**/like/**/'admin'# %252f%252a*/union%252f%252a*/select%252f%252a*/password%252f%252a*/from%252f%252a*/users%252f%252a*/where%252f%252a*/username%252f%252a*/like%252f%252a*/'admin'# ascii編碼 Test 等價于CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116) 16進制 select * from users where username = test1; select * from users where username = 0x7465737431; unicode編碼對部分符號的繞過 單引號=> %u0037 %u02b9 空格=> %u0020 %uff00 左括號=> %u0028 %uff08 右括號=> %u0029 %uff09
空格繞過
一般繞過空格過濾的方法有以下幾種方法來取代空格
/**/ () 回車(url編碼中的%0a) `(tap鍵上面的按鈕) tap 兩個空格
對or and xor not 繞過
or = || and = && xor = | 或者 ^ # 異或,例如Select * from cms_users where userid=1^sleep(5); not = !
雙寫繞過
在某一些簡單的waf中,會將關鍵字select等使用replace()函數置換為空。當關鍵詞被過濾時可以采用雙寫的方式,在經過waf的處理之后又變成select,達到繞過的要求。
and寫成anandd select寫成seleselectct
大小寫變種:
當關鍵詞被過濾時,可嘗試變換大小寫進行繞過。
UniOn SeleCt
對等號=繞過
不加通配符的like執行的效果和 = 一致,所以可以用來繞過。
1. 正常加上通配符的like:
Select * from cms_users where username like "ad%"; 1
- 不加上通配符的like可以用來取代=:
Select * from cms_users where username like "admin"; 1
- regexp:MySQL中使用 REGEXP 操作符來進行正則表達式匹配
Select * from cms_users where username REGEXP "admin"; 1
4 .使用大小于號來繞過
Select * from cms_users where userid>0 and userid<2; 1
- <> 等價于 != ,所以在前面再加一個 ! 結果就是等號了
Select * from cms_users where !(username <> "admin");
畸形HTTP請求
當向WEB服務器發送畸形的、非RFC2616標準的HTTP請求時,WEB服務器出于兼容的目的,會盡可能解析HTTP請求。若WEB服務器的兼容方式與WAF不一致,則可能會出現繞過的情況。比如: GET id.php?id=1%20union/**/select這個請求,無請求的協議字段,也沒有HOST字段,但Apache對這個請求的處理默認會設置協議為HTTP/0.9,HOST則默認會使用Apache默認的servername;
使用動態查詢執行
許多數據庫都允許動態執行SQL查詢,只需向只需向執行查詢的數據庫函數傳遞一個包含SQL查詢的字符串即可。如果找到了SQL注入點,但卻被過濾器阻止注入,那就可以嘗試動態執行進行繞過。
不同的數據庫中動態查詢執行的實現會有所不同;
在SQL Server中,可以使用exec函數執行一個字符串格式的查詢,例如:exec('select * from users');
Oracle可使用execute immediate命令執行一個字符串格式的查詢,例如:execute immediate 'select * from users'。
數據庫提供了多種操作字符串的方法。想使用動態執行的關鍵是使用字符串操作函數將過濾器允許的輸入轉換成一個包含所需要查詢的字符串。最簡單的情況,可以使用字符串連接技術將較小的部分構造成一個字符串。不同數據庫使用不同的語法連接字符串。若select被過濾,可使用(但連接符在http請求中被提交時需進行URL編碼)
Oracle:'se'||'lect' SQL Server:'se'+'lect' MySQL:'se' 'lect'
也可使用字符串操作函數reverse()、substr()、replace()等。
使用空字節
通常需要繞過的SQL注入漏洞過濾器都是在應用程序自身的代碼之外(IDS、WAF),這些組件通常由C++編寫,所以我們可以針對這些語言的特性進行繞過,比如可以使用空字節攻擊來避開輸入過濾器并將漏洞輸入至后臺應用程序中。
空字節之所以能起作用,是因為原生代碼和托管代碼分別采用不同的方法來處理空字節。在原生代碼中,根據字符串起始位置到出現第一個空字節的位置來確定字符串長度(空字節終止字符串)。而在托管代碼中,字符串對象包含一個字符數組和一條單獨的字符串長度記錄。
這種差異意味著原生過濾器在處理輸入時,如果遇到空字節,便會停止處理,因為在過濾器看來,空字節代表字符串的結尾。如果空字節之前的輸入是良性的,那么過濾器將不會阻止該輸入。不過在托管代碼語境中,應用在處理相同的輸入時,會將空字節后面的輸入一同處理。所以只需要在過濾器阻止的字符前提供一個采用URL編碼的空字節(%00)即可。
id=1%00' union select *password from users where username='admin'-- 。
二次注入
防御者可能在用戶輸入惡意數據時對其中的特殊字符進行了轉義處理,但在惡意數據插入到數據庫時被處理的數據又被還原并存儲在數據庫中,當WEB程序調用存儲在數據庫中的惡意數據并執行SQL查詢時,產生二次注入。
二次注入雖然是SQL注入的一種,但挖掘二次注入需要對應用程序有完整的理解,需要知道應用程序的邏輯,所以自動化掃描很難發現,基本靠人工發現。
0x06 測試過程
通過手工或工具進行SQL注入測試,驗證系統相關功能頁面,查看是否能進行數據查詢獲取相關敏感數據。
測試案例1
- 系統某鏈接中的POST參數:hidZWCLFS存在SQL注入漏洞。如下圖所示:

- 除上述鏈接外,其他鏈接同樣存在若干SQL注入漏洞,需要對系統POST參數進行統一過濾,下列給出部分含有SQL注入漏洞的鏈接。如圖所示:

測試案例2
- 使用椰樹V1.9-web安全掃描工具 ( 提取碼:nn1k)對測試站點進行掃描。將url鏈接放入工具中,點擊掃描網站,并且等狀態欄為done時,掃描完成,如下圖所示,發現2個注入點。

- 對剛發現的注入點進行注入,選擇SQL INJECTION POC。

- 注入成功,可查看用戶名、加密過后的密碼等數據。


- 使用MD5解密工具進行解密,成功獲取用戶名、密碼。

再用御劍等目錄爆破工具,掃描網站后臺,使用SQL注入出的用戶名密碼進行登錄。

測試案例3
CVE-2021-35042
- 訪問列表視圖 http://your-ip:8000/vuln/

- 添加?order=-id到 GET 參數,可看到按 id 按照降序排列的數據。

- 根據以上信息可以構造報錯注入進行攻擊獲取數據信息。
?order=vuln_collection.name);select updatexml(1, concat(0x7e,(select @@version)),1)%23
執行payload后,系統返回數據庫版本信息。

- 執行獲取用戶名、密碼的payload,成功利用系統的SQL注入漏洞獲取用戶名、密碼。

0x07 風險分析
攻擊者可以通過構造特殊URL的手段,利用SQL注入漏洞:
- 使得系統業務功能異常或者失效;
- 惡意的破壞,比如修改數據,刪數據,刪表等惡意破壞;
- 探查數據庫類型,結構,獲取數據庫敏感數據,造成數據泄露;
- 修改數據庫配置,控制服務器,進行惡意活動等
- 在某些情況下能執行操作系統命令
0x08 加固建議
想要更好的防止SQL注入攻擊,就必須清楚一個概念:數據庫只負責執行SQL語句,根據SQL語句來返回相關數據。數據庫并沒有什么好的辦法直接過濾SQL注入,哪怕是存儲過程也不例外,了解此點后,應該明白,防御SQL注入,還是需要從代碼入手。
- 對用戶輸入的數據進行全面安全檢查或過濾,采用一些成熟的防注入產品。
服務器可以安裝安全狗、360網站衛士等安全工具,數據庫中的敏感信息加密后存放,嚴格控制數據庫用戶權限。
- 使用預編譯語句,綁定變量(最佳方式),這樣SQL語句的語義不會發生改變;
- 檢查數據類型,限制郵箱、時間、日期等數據的格式;
- 使用安全的存儲過程;
- 檢查輸入數據的數據類型;
- 使用安全函數,推薦OWASP ESAPI項目的安全函數,如:ESAPI.encoder().encoderForSQL(new OracleCodec(),queryparam)。
- 為所有數據庫訪問使用參數化查詢并正確的參數化集成到查詢中的每個可變數據項(防御二次注入);
參考 https://blog.csdn.net/weixin_42478365/article/details/119300607 https://blog.csdn.net/weixin_43123409/article/details/12133365
黑白之道發布、轉載的文章中所涉及的技術、思路和工具僅供以安全為目的的學習交流使用,任何人不得將其用于非法用途及盈利等目的,否則后果自行承擔!