第32關 寬字節注入
查看一下本關的源代碼:
function check_addslashes($string)
// 定義一個用于過濾特殊字符的函數,目的是轉義可能用于注入的特殊符號
{$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);
// 轉義反斜杠:將單個反斜杠替換為兩個反斜杠(防止反斜杠被誤用為轉義符)$string = preg_replace('/\'/i', '\\\'', $string);
// 轉義單引號:將單引號替換為“反斜杠+單引號”(防止單引號閉合SQL字符串)$string = preg_replace('/\"/', "\\\"", $string);
// 轉義雙引號:將雙引號替換為“反斜杠+雙引號”(防止雙引號閉合SQL字符串) return $string; // 返回處理后的字符串
}
自定義了一個函數,過濾了單引號,雙引號和反斜杠。這里輸入的單引號被轉義成反斜杠加單引號。
但是在源代碼中寫到本關使用GBK編碼,GBK為雙字節編碼,一個漢字由兩個字節組成。利用多字節字符編碼特性,構造特殊字符,使原本被轉義的字符在編碼轉換過程中逃逸出來,從而產生了寬字節注入攻擊。
舉例,%27 是單引號 ' 的URL編碼。%bf 是一個特定的字節(十六進制為0xBF),它屬于GBK編碼的第一個字節范圍,所以當它后面跟著一個字節(比如0x5C,即反斜杠)時,它們會組合成一個GBK字符。
漏洞觸發過程:
1. 用戶輸入:%bf%27 (即0xBF 0x27)。
2. PHP的轉義函數檢測到單引號(0x27),于是在它前面加上反斜杠(0x5C)。所以進一步變成為:0xBF, 0x5C, 0x27。
3. 然后這個字符串被拼接到SQL語句中,SQL語句在數據庫里執行時,數據庫使用的是GBK編碼,它會將兩個字節看作一個漢字。其中0xBF和0x5C(反斜杠)組合在一起,被當作一個GBK字符(這個字符是“縗”,讀cuī)。這樣,0x27(單引號)就獨立出來了,導致轉義失效。
測試:
這里只輸入一個單引號會被過濾,利用寬字節注入使單引號不被轉義,則union查詢成功。
?第33關 使用內置函數的寬字節注入
本關使用的是PHP內置的addslashes函數,它的作用是添加反斜杠進行轉義。區別在于上一關是自定義函數,這一關是用內置函數,但都是寬字節注入,解法相同。