原理
mysql 在使用 GBK 編碼的時候,會認爲兩個字符爲一個漢字,例如%aa%5c 就是一個漢字(前一個 ascii 碼大於 128 才能到漢字的範圍)。我們在過濾 ’ 的時候,往往利用的思路是將‘轉換爲\’(轉換的函數或者思路會在每一關遇到的時候介紹)。
PHP 自帶一些轉義特殊字符的函數,如addslashes()
,mysql_real_escape_string()
,mysql_escape_string()
等,這些函數可用來防止 SQL 注入。
如id=1'or'1'='1
,單引號本用來閉合語句,這些函數會自動轉義這些閉合的單引號,在這些單引號前面加上轉義符\
,變爲1\'or\'1\'=\'1
,如此在 SQL 查詢中是一個普通的字符串,不能進行注入。
而網站在過濾'
的時候,通常的思路就是將'
轉換爲\'
,因此我們在此想辦法將'
前面添加的\
去掉,一般有兩種思路:
-
%bb吃掉
\
如果程序的默認字符集是GBK
等寬字節字符集,就有可能產生寬字節注入,繞過上述過濾。
若在 PHP 中使用mysql_query("set names gbk")
將默認字符集設爲GBK
,而使用addslashes()
轉義用戶輸入,這時如果用戶輸入%bb%27
,則addslashes()
會在%27
前面加上一個%5c
字符,即轉義字符\
。
而 MySQL 在使用GBK
編碼時,會認爲兩個字符爲一個漢字,%bb%5c
是一個寬字符(前一個 ASCII 碼大於 128 才能到漢字的範圍),也就是籠
,也就是說%bb%5c%27
=籠'
,這樣單引號就未被轉義能閉合語句,從而產生 SQL 注入。%bb
並不是唯一一個可以產生寬字節注入的字符,理論上%81
-%FE
均可。 -
過濾
\'
中的\
構造%bb%5c%5c%27
,addslashes()
會在兩個%5c
和%27
前都加上\
即%5c
,變爲%bb %5c%5c %5c%5c %5c%27
,但寬字符集認爲%bb%5c
是一個字符即籠
,則變爲%bb%5c %5c%5c %5c%5c %27
即籠\\\\'
,四個\
正好轉義爲兩個\
,即'
未被轉義。這也是 bypass 的一種方法。