SQL黑客注入防禦與繞過的多種姿勢
一、 PHP幾種防禦姿勢
1. 關閉錯誤提示
說明:
PHP配置文件php.ini中的display_errors=Off,這樣就關閉了錯誤提示。
2. 魔術引號
說明:
當php.ini里的magic_quotes_gpc=On時。提交的變數中所有的單引號(")、雙引號(")、反斜線()與 NUL(NULL 字元)會自動轉為含有反斜線的轉義字元。
魔術引號(Magic Quote)是一個自動將進入 PHP 腳本的數據進行轉義的過程。(對所有的 GET、POST 和 COOKIE 數據自動運行轉義)
PHP 5.4 之前 PHP 指令 magic_quotes_gpc 默認是 on。
本特性已自PHP 5.3.0 起廢棄並將自 PHP 5.4.0 起移除,在PHP 5.4.O 起將始終返回 FALSE。
3. addslashes
說明:
addslashes函數,它會在指定的預定義字元前添加反斜杠轉義,這些預定義的字元是:單引號(")、雙引號(")、反斜線()與 NUL(NULL 字元)。
這個函數的作用和magic_quotes_gpc一樣。所以一般用addslashes前會檢查是否開了magic_quotes_gpc。
magic_quotes_gpc與addslashes的區別用法:
1)對於magic_quotes_gpc=on的情況
我們可以不對輸入和輸出資料庫的字元串數據作addslashes()和stripslashes()的操作,數據也會正常顯示。
如果此時你對輸入的數據作了addslashes()處理,那麼在輸出的時候就必須使用stripslashes()去掉多餘的反斜杠。
2)對於magic_quotes_gpc=off 的情況
必須使用addslashes()對輸入數據進行處理,但並不需要使用stripslashes()格式化輸出,
因為addslashes()並未將反斜杠一起寫入資料庫,只是幫助mysql完成了sql語句的執行。
4. mysql_real_escape_string
說明:
mysql_real_escape_string()函數轉義 SQL 語句中使用的字元串中的特殊字元。
下列字元受影響:
x00
" " x1a
如果成功,則該函數返回被轉義的字元串。如果失敗,則返回 false。
本擴展自 PHP5.5.0 起已廢棄,並在自 PHP 7.0.0 開始被移除。
因為完全性問題,建議使用擁有Prepared Statement機制的PDO和MYSQLi來代替mysql_query,使用的是mysqli_real_escape_string
5. htmlspecialchars()
說明:
htmlspecialchars()函數把預定義的字元轉換為 HTML實體。
預定義的字元是:
& (和號)成為 & " (雙引號)成為 " " (單引號)成為 " < (小於)成為=""><> (大於)成為 >6. 用正則匹配替換來過濾指定的字元
preg_match preg_match_all() preg_replace7. 轉換數據類型
說明:
根據「檢查數據類型」的原則,查詢之前要將輸入數據轉換為相應類型,如uid都應該經過intval函數格式為int型。
8. 使用預編譯語句
說明:
綁定變數使用預編譯語句是預防SQL注入的最佳方式,因為使用預編譯的SQL語句語義不會發生改變,在SQL語句中,變數用問號?表示,攻擊者無法改變SQL語句的結構,從根本上杜絕了SQL注入攻擊的發生。
代碼示例:
二、 幾種繞過姿勢
下面列舉幾個防禦與繞過的例子:
例子1:addslashes
防禦:
這裡用了addslashes轉義。
繞過:
將字元串轉為16進位編碼數據或使用char函數(十進位)進行轉化(因為資料庫會自動把16進位轉化)
用注釋符去掉輸入密碼部分如「-- /* #」
payload:
http://localhost/injection/user.php?username=admin-- hack(因為有的SQL要求--後要有空格,所以此處加上了hack)
http://localhost/injection/user.php?username=admin/*(escape不轉義/*)
http://localhost/injection/user.php?username=admin%23(這裡的%23即為#,注釋掉後面的密碼部分。注意IE瀏覽器會將#轉換為空)
http://localhost/injection/user.php?username=0x61646d696e23(admin# -->0x61646d696e23)
http://localhost/injection/user.php?username=CHAR(97,100, 109, 105, 110, 35)(admin# -->CHAR(97, 100, 109, 105, 110, 35))
關於編碼原理:
因為一般前端JavaScript都會escape()、encodeURL或encodeURIComponent編碼再傳輸給伺服器,主要為encodeURL,如下,所以可以利用這點。
JavaScript代碼如:
攔截請求:
1)escape( )
對ASCII字母、數字、標點符號"@* _ + - . /"不進行編碼。在u0000到u00ff之間的符號被轉成%xx的形式,其餘符號被轉成%uxxxx的形式。(注意escape()不對"+"編碼,而平時表單中的空格會變成+)
2) encodeURL
對" ; / ? : @ & = + $ , # " "不進行編碼。編碼後,它輸出符號的utf-8形式,並且在每個位元組前加上%。
3) encodeURIComponent
用於對URL的組成部分進行個別編碼,而不用於對整個URL進行編碼。
常用編碼:
@ * _ + - ./ ; ? : @ & = + $ , # " 空格
轉碼工具可用:
例子2:匹配過濾
防禦:繞過
關鍵詞and,or常被用做簡單測試網站是否容易進行注入攻擊。這裡給出簡單的繞過使用&&,||分別替換and,or。
過濾注入: 1 or 1 = 1 1 and 1 = 1
繞過注入: 1 || 1 = 1 1 && 1 = 1
關於preg_match過濾可以看參考文章,文章里講得很詳細了。
例子3:strstr
防禦:
strstr ()查找字元串的首次出現,該函數區分大小寫。如果想要不區分大小寫,使用stristr()。(注意後面這個函數多了個i)
繞過:
strstr()函數是對大小寫敏感的,所以我們可以通過大小寫變種來繞過
payload:
http://localhost/injection/user.php?id=1uNion select null,null,null例子4:空格過濾
防禦:
繞過:
1)使用內聯注釋。
2)使用換行符代替空格。注意伺服器若為Windows則換行符為%0A%0D,Linux則為%0A。
http://localhost/injection/user.php?id=1/**/and/**/11=1 http://localhost/injection/user.php?id=1%0A%0Dand%0A%0D1=1例子5:空位元組
通常的輸入過濾器都是在應用程序之外的代碼實現的。比如入侵檢測系統(IDS),這些系統一般是由原生編程語言開發而成,比如C++,為什麼空位元組能起作用呢,就是因為在原生變成語言中,根據字元串起始位置到第一個出現空位元組的位置來確定字元串長度。所以說空位元組就有效的終止了字元串。
繞過:
只需要在過濾器阻止的字元串前面提供一個採用URL編碼的空位元組即可。
payload:
例子6:構造故意過濾
防禦:
繞過:
文件的63行開始可以看到,此處將傳入的%27和%2527都進行刪除處理,也就是還沒傳入資料庫前就已經被該死的程序吃了,但是在67行看到他還吃了*,這樣我們就有辦法了,我們構造%*27,這樣程序吃掉星號*後,%27就會被傳入。
payload:
http://localhost/injection/user.php?id%3D1%*27%*20and%*20%*271%*27%3D%*271(id=1" and "1"="1-->id%3D1%*27%*20and%*20%*271%*27%3D%*271)
推薦閱讀:
※黑客信息搜集網站大全
※如何充分利用Windows防火牆抵禦黑客進攻?
※如何自學CMD?
※白夜追兇裡面的關宏峰和黑客大壯哪來的錢衣食住行?