10-Web安全——SQL注入WAF繞過之寬字節注入

addslashes()函數在指定的預定義字符前添加反斜槓,這些字符是單引號('),雙引號("),反斜線(\)與NUL(NULL字符)。例如客戶端提交的參數中如果含有單引號,雙引號等這些特殊字符,addslashes函數則會在單引號前加反斜線“\”,將單引號轉義成沒有功能性的字符。

 

舉個栗子:

以查詢用戶名爲1’的信息爲例,username中的參數爲1',MySQL數據庫在解析這條SQL語句時,會把1後面的單引號認爲是閉合符號要求再輸入一個單引號閉合,而不是當做username參數的一部分來處理,從而導致數據庫只查詢用戶名爲1的信息,而不是查詢1'的信息。

 

在示例中數據庫提示我們要求再輸入一個單引號,然後輸入分號“;”結束SQL語句,查詢出來的結果爲0,因爲users表中確實沒有用戶名爲1的信息。

 

如果想要把單引號作爲username參數的一部分的話,可以使用反斜線對單引號進行轉義,如下所示:

在單引號前面加一個反斜線後,數據庫在解析SQL語句時就會將單引號作爲一個普通字符對待,沒有特殊含義,也不會把單引號識別爲閉合方式,而是作爲username參數中的一部分。

 

addslashes函數過濾的作用:當輸入閉合符號'時把在'前加上反斜線\轉義爲普通字符,導致無法閉合。

 

 

在Less-23中源代碼中輸入?id=1\'進行測試:

發現後臺仍然把我們輸入的反斜線給轉義過濾掉了,頁面最終返回的是1\\\',第一個反斜線將第二個反斜線轉義了,然後第三個反斜線把單引號給轉義了。

 

 

分析Less-32源代碼:

function check_addslashes($string)
{
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);                //escape any backslash
    $string = preg_replace('/\'/i', '\\\'', $string);                               //escape single quote with a backslash
    $string = preg_replace('/\"/', "\\\"", $string);                                //escape double quote with a backslash
    return $string;
}

 

從後臺的過濾代碼中可知,使用這種方式是不可能繞過的,當然addslashes()函數也會有侷限性,一般我們會採取的方法:GBK字符編碼和網頁URL編碼兩種方式。

 

 

這裏主要介紹GBK字符編碼繞過:

GBK編碼,是在GB2312-80標準基礎上的內碼擴展規範,使用了雙字節編碼方案,其編碼範圍從8140至FEFE(剔除xx7F),共23940個碼位,共收錄了21003個漢字,完全兼容GB2312-80標準,支持國際標準ISO/IEC10646-1和國家標準GB13000-1中的全部中日韓漢字,幷包含了BIG5編碼中的所有漢字——(摘自百度百科)。

 

字符反斜線“\” 的ASCII碼值是5C,佔用一個字節,GBK編碼方式可以將反斜線“\”轉換爲一個服務器數據庫不識別的漢字,即在5C前面拼接組合一個字符0xdf,那麼數據庫就會將0xdf5c轉換爲一個不識別的漢字,這樣數據庫就會將其忽略掉。

 

假設當前數據庫使用的是GBK編碼集,那麼數據庫會把兩個字符識別爲一個漢字,所以可以使用一些字符和經過轉義後多出來的反斜線“\”組合成兩個字符,從而變成數據庫不識別的漢字字符,從而破壞對單引號,雙引號的轉義,使其參數閉合。

 

 

再舉個栗子

 

假設當前數據庫使用GBK編碼集,當,數據庫會將輸入的參數%df%5c解析爲兩個字節:

 

其中%df爲高位字節,編碼位是223;%5c爲低位字節,編碼位是92;%df%5c的GBK編碼取值範圍就是:第一個字節是129—254,第二個字節是64—254,數據庫會按照GBK編碼將%df%5c解析成一個漢字,這樣“\”就會失去原來的作用。

在上圖中,數據庫將參數%df%5c按照GBK編碼集解析成上圖中的漢字:運,這種方式就是寬字節注入。

 

 

寬字節注入有前提:要求目標MYSQL數據庫的編碼方式是GBK編碼,並且客戶端必須和數據庫的編碼方式一致,這樣才能使用寬字節注入方式,寬字節注入過程如下所示:

 

輸入參數:?id=1%df' and 1=1 --+,進行測試,結果如下

測試頁面返回的結果是:1�\' and 1=1 --。

由於輸入的參數中有單引號,後臺使用了反斜線對單引號過濾,使得參數實際上替換成了1�\' and 1=1 --,並且數據庫會將“�\”字符解析成一個漢字,也就是下圖中紅色部分,從而繞過WAF。

 

 

後臺替換成的SQL語句是這樣的:SELECT * FROM users WHERE id='1%df\' and 1=1 --+' LIMIT 0,1,並且該SQL語句可以正常執行:

 

總結:

寬字節注入有個前提:要求目標MYSQL數據庫的編碼方式是GBK編碼,並且客戶端必須和數據庫的編碼方式一致

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