您好,登錄后才能下訂單哦!
0x00:前言
關于sql注入,經久不衰,現在的網站一般對sql注入的防護也相對加強了,2016年的***測試報告中,出現最多的是xss(跨站腳本***)和明文傳輸等,但是對sql注入的利用方式,也相對成熟,詳細了解sql注入,可以參考之前的文章。http://wt7315.blog.51cto.com/10319657/1828167
今天主要分享下sql注入中的報錯型,在大多網上的文章會列出類似于公式的句子,卻沒解釋為什么要使用這樣的函數,為什么使用這個函數會出現報錯而導致sql注入。
0x01:報錯過程
我們先來了解幾個函數。
1. rand
()用于產生一個0~1的隨機數。
2.floor
()向下取整
3. rand()函數生成0~1的函數,使用floor函數向下取整,值是固定的“0”,我們將rand*2,得到的值就是不固定的,“0”或者“1”。
4.我們再來查詢下當前的數據庫,我使用的是“dvwa”數據庫
5.concat()將符合條件的同一列中的不同行數據拼接,為了待會便于觀察,在此插入0x3a,0x3a是十六進制的“:”。
7.查詢名字太長,我們來起個別名。
8.我們再一次進行查詢,information_schema.tables有多少個表哥,會顯示多少列。
9.group by 依據我們想要的規矩對結果進行分組。
10. count() 統計元祖的個數(相當于求和)。
11.接著,我們多重復幾次。
0x02:
rand()和rand(0)
1.加上隨機因子后,執行多次每次都會報錯。為了更徹底的說明報錯原因,直接把隨機因子去掉,再來一遍看看。
2.先看一條記錄的時候,一條記錄的話 無論執行多少次也不報錯
3.然后增加一條記錄,兩條記錄的話 結果就變成不確定性了
隨機出現報錯,然后再插入一條,三條記錄之后,也和2條記錄一樣進行隨機報錯。由此可見報錯和隨機因子是有關聯的
floor(rand(0)*2)報錯的原理是恰恰是由于它的確定性,因為floor(rand()*2)不加隨機因子的時候是隨機出錯的,而在3條記錄以上用floor(rand(0)*2)就一定報錯,由此可猜想floor(rand()*2)是比較隨機的,不具備確定性因素,而floor(rand(0)*2)具備某方面的確定性。
我們分別對floor(rand()*2)和floor(rand(0)*2)在多記錄表中執行多次。
可以看到,floor(rand()*2)毫無規律可言,而floor(rand(0)*2)是有規律的。
那么mysql在遇到select count(*) from tables group by x;這語句的時候會建立一個虛擬表(實際上就是會建立虛擬表),整個工作流程就會如下圖所示:
1.先建立虛擬表,如下圖(其中key是主鍵,不可重復)
2.開始查詢數據,取數據庫數據,然后查看虛擬表存在不,不存在則插入新記錄,存在則count(*)字段直接加
由此看到 如果key存在的話就+1, 不存在的話就新建一個key。
其實mysql官方有給過提示,就是查詢的時候如果使用rand()的話,該值會被計算多次,那這個“被計算多次”到底是什么意思,就是在使用group by的時候,floor(rand(0)*2)會被執行一次,如果虛表不存在記錄,插入虛表的時候會再被執行一次,我們來看下floor(rand(0)*2)報錯的過程就知道了,從0x04可以看到在一次多記錄的查詢過程中floor(rand(0)*2)的值是定性的,為011011…(記住這個順序很重要),報錯實際上就是floor(rand(0)*2)被計算多次導致的。
我們做下整理。
1.查詢前默認會建立空虛擬表。
2.取第一條記錄,執行floor(rand(0)*2),發現結果為0(第一次計算),查詢虛擬表,發現0的鍵值不存在,則floor(rand(0)*2)會被再計算一次,結果為1(第二次計算),插入虛表,這時第一條記錄
3.查詢第二條記錄,再次計算floor(rand(0)*2),發現結果為1(第三次計算),查詢虛表,發現1的鍵值存在,所以floor(rand(0)*2)不會被計算第二次,直接count(*)加1,第二條記錄查詢完畢查詢完畢
4.查詢第三條記錄,再次計算floor(rand(0)*2),發現結果為0(第4次計算),查詢虛表,發現鍵值沒有0,則數據庫嘗試插入一條新的數據,在插入數據時floor(rand(0)*2)被再次計算,作為虛表的主鍵,其值為1(第5次計算),然而1這個主鍵已經存在于虛擬表中,而新計算的值也為1(主鍵鍵值必須唯一),所以插入的時候就直接報錯了
整個查詢過程floor(rand(0)*2)被計算了5次,查詢原數據表3次,所以這就是為什么數據表中需要3條數據,使用該語句才會報錯的原因。
0x04:loor(rand()*2)報錯
由于沒加入隨機因子,所以floor(rand()*2)是不可測的,因此在兩條數據的時候,只要出現下面情況,即可報錯
前面幾條記錄查詢后不能讓虛表存在0,1鍵值,如果存在了,那無論多少條記錄,也都沒辦法報錯,因為floor(rand()*2)不會再被計算做為虛表的鍵值,這也就是為什么不加隨機因子有時候會報錯,有時候不會報錯的原因。
0x05:updatexml報錯
MySQL 5.1.5版本中添加了對XML文檔進行查詢和修改的函數,分別是ExtractValue()和UpdateXML()
我們要學習的便是mysql里的修改函數即updatexml函數
其實也有extractvalue注入 以后的文章再做介紹。
先來做如下操作:
執行一下報錯payload:
and updatexml(1,concat(null,(select @@version),null),1);
updatexml的爆錯原因很簡單,updatexml第二個參數需要的是Xpath格式的字符串。我們輸入的顯然不符合。故報錯由此報錯。
updatexml的最大長度是32位的,所以有所局限(PS:但是應對大多的已經足夠。)如果密碼長度超過了32位就不會被顯示出來。
0x06:其余報錯函數
extractvalue() id = 1 and (extractvalue(1, concat(0x5c,(selectuser()))))
exp() id =1 and EXP(~(SELECT * from(select user())a))
這六個函數總的來說歸于一類
GeometryCollection()
id = 1 AND GeometryCollection((select * from (select * from(select user())a)b))
polygon()
id =1 AND polygon((select * from(select * from(select user())a)b))
multipoint()
id = 1 AND multipoint((select * from(select * from(select user())a)b))
multilinestring()
id = 1 AND multilinestring((select * from(select * from(select user())a)b))
linestring()
id = 1 AND LINESTRING((select * from(select * from(select user())a)b))
multipolygon()
id =1 AND multipolygon((select * from(select * from(select user())a)b))
基于篇幅問題,剩下就不解釋原理了,有機會,后面還會詳細的介紹。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。