最新寬位元組注入攻擊和程式碼分析技術

Ms08067安全实验室發表於2024-03-12

寬位元組注入攻擊

寬位元組注入攻擊的測試地址在本書第2章。

訪問id=1',頁面的返回結果如圖4-51所示,程式並沒有報錯,反而多了一個轉義符(反斜槓)。

4-51

從返回的結果可以看出,引數id=1在資料庫查詢時是被單引號包圍的。當傳入id=1'時,傳入的單引號又被轉義符(反斜槓)轉義,導致引數ID無法逃出單引號的包圍,所以一般情況下,此處是不存在SQL隱碼攻擊漏洞的。不過有一個特例,就是當資料庫的編碼為GBK時,可以使用寬位元組注入。寬位元組的格式是在地址後先加一個%df,再加單引號,因為反斜槓的編碼為%5c,而在GBK編碼中,%df%5c是繁體字“連”,所以這時,單引號成功“逃逸”,報出MySQL資料庫的錯誤,如圖4-52所示。

4-52

由於輸入的引數id=1',導致SQL語句多了一個單引號,所以需要使用註釋符來註釋程式自身的單引號。訪問id=1%df'%23,頁面返回的結果如圖4-53所示,可以看到,SQL語句已經符合語法規範。

4-53

使用and 1=1和and 1=2進一步判斷注入,訪問id=1%df' and 1=1%23和id=1%df' and 1=2%23,返回結果分別如圖4-54和圖4-55所示。

4-54

4-55

and 1=1程式返回正常時,and 1=2程式返回錯誤,判斷該引數ID存在SQL隱碼攻擊漏洞,接著使用order by查詢資料庫表的欄位數量,最後得知欄位數為5,如圖4-56所示。

4-56

因為頁面直接顯示了資料庫中的內容,所以可以使用Union查詢。與Union注入一樣,此時的Union語句是union select 1,2,3,4,5,為了讓頁面返回Union查詢的結果,需要把ID的值改為負數,結果如圖4-57所示。

4-57

然後嘗試在頁面中2的位置查詢當前資料庫的庫名(user()),語句如下:

id=-1%df' union select 1,user(),3,4,5%23

返回的結果如圖4-58所示。

4-58

查詢資料庫的表名時,一般使用以下語句:

select table_name from information_schema.tables where table_schema='test' limit 0,1

此時,由於單引號被轉義,會自動多出反斜槓,導致SQL語句出錯,所以此處需要利用另一種方法:巢狀查詢。就是在一個查詢語句中,再新增一個查詢語句,更改後的查詢資料庫表名的語句如下:

select table_name from information_schema.tables where table_schema=(select database()) limit 0,1

可以看到,原本的table_schema='test'變成了table_schema=(select database()),因為select database()的結果就是'test',這就是巢狀查詢,結果如圖4-59所示。

4-59

從返回結果可以看到,資料庫的第一個表名是users,如果想查詢後面的表名,則需要修改limit後的數字,這裡不再重複。使用以下語句嘗試查詢users表裡的欄位:

select column_name from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1) limit 0,1

這裡使用了三層巢狀,第一層是table_schema,它代表庫名的巢狀,第二層和第三層是table_name的嵌套。可以看到,語句中有兩個limit,前一個limit控制表名的順序,後一個limit則控制欄位名的順序。如果這裡查詢的不是emails表,而是users表,則需要更改limit的值。如圖4-60所示,後面的操作與Union注入相同,這裡不再重複。

4-60



寬位元組注入程式碼分析

在寬位元組注入頁面中,程式獲取GET引數ID,並對引數ID使用addslashes()轉義,然後拼接到SQL語句中,進行查詢,程式碼如下:

<?php $con=mysqli_connect("localhost","root","123456","test"); if (mysqli_connect_errno()) { echo "連線失敗: " . mysqli_connect_error(); } mysqli_query($con, "SET NAMES 'gbk'");

$id = addslashes($_GET['id']); $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; $result = mysqli_query($con, $sql) or die(mysqli_error($con)); $row = mysqli_fetch_array($result);

if($row){ echo $row['username']. " : " . $row['address']; }else { print_r(mysqli_error($con));} echo "<br>The Query String is : ".$sql ."<br>";?>

當訪問id=1'時,執行的SQL語句如下:

SELECT * FROM users WHERE id='1\''

可以看到,單引號被轉義符“\”轉義,所以在一般情況下,是無法注入的。由於在資料庫查詢前執行了SET NAMES 'GBK',將資料庫編碼設定為寬位元組GBK,所以此處存在寬位元組注入漏洞。

PHP中,透過iconv()進行編碼轉換時,也可能存在寬字元注入漏洞。

Ms08067安全實驗室專注於網路安全知識的普及和培訓,是專業的“圖書出版+培訓”的網路安全線上教育平臺,專注於網路安全領域中高階人才培養。

平臺已開設Web安全零基礎就業,Web高階安全攻防進階,紅隊實戰攻防特訓,Java程式碼安全審計,惡意程式碼分析與免殺實戰,CTF基礎實戰特訓營,網路安全應急響應,安全工具開發,AI與網路安全等系統培訓課程。實驗室出版安全圖書《Web安全攻防:滲透測試實戰指南》、《內網安全攻防:滲透測試實戰指南》、《Python安全攻防:滲透測試實戰指南》、《Java程式碼審計:入門篇》等。

掃描客服微信 獲取更多課件+學習資料

相關文章