SQL注入--雙注入的學習

0x1 須要用到的MySQL函數html


 

count():用來統計表中或數組中記錄的一個函數 count(*)某表中全部的列mysql

floor():返回小於等於該值的最大整數【向下取整】
sql

 

 

 

 

rand(): 產生隨機數
數據庫

 

 


 

0x2原理分析數組

接下來咱們再分析其報錯的造成 緣由:函數

先談group by 函數:spa

在表中再插入兩條數據,name值都爲「bbb」:3d

mysql> INSERT INTO test VALUES("3","bbb");
mysql> INSERT INTO test VALUES("4","bbb");

成功後表以下:code

1547706801693

這時候咱們使用group by 語句時,MySQL會將查詢結果分類彙總,重複的內容會合併爲一項:htm

mysql> SELECT name FROM test GROUP BY name;

1547707005212

這時候再使用count()函數就能夠對不一樣的條目計數:

mysql> SELECT count(*),name FROM test GROUP BY name;

如圖:aaa有一條,bbb有3條

1547707132342

其背後的實現原理以下:

在執行group by name語句時,MySQL會在內部創建一個虛擬表,用來儲存列的數據,表中會有一個group_key值做爲表的主鍵,這裏的主鍵就是用來分類的name列中獲取,當查詢數據時,取數據庫數據,而後查看虛擬表中存在不,不存在則插入新記錄

1547707392629

當讀取到第一行數據時,aaa不存在,將aaa放入主鍵列中,1放在id列中

1547707587564

而後繼續往下走,到了bbb,不存在,也放進去

1547707641420

往下執行,遇到多餘的bbb,已經有bbb存在,就彙總在一塊兒,內部狀況以下:

1547707746563

以下,最後在查詢的時候根據group by內部的實現方式返回分類後的結果:

1547708050507

當咱們加上count(*)函數時,操做過程爲:查看虛擬表是否存在該主鍵值,不存在則插入新記錄,存在則count(*)字段直接加1

這樣就能對上面的分類結果進行統計,而後將統計結果返回:

1547708171151

因此雙查詢報錯的關鍵就在這裏,主要的緣由在於rand()函數在group by的過程當中被觸發了屢次

0x3 報錯原理


讓咱們回看一下構造的報錯語句:

mysql> SELECT count(*),concat((SELECT database()),"~",floor(rand()*2))as a FROM test GROUP BY a;

執行前虛擬表爲空:

1547708989795

當第一次執行時,group by 分組,其取的數據的是以a爲別名的這條語句,假設這時的concat((SELECT database()),"~",floor(rand()*2))生成結果爲sql_test~0,group就以sql_test~0查詢虛擬表,發現表中沒有該值的主鍵,因而將這條語句的結果插入到虛擬表中。

注意!是將這條語句的結果插入到虛擬表中,而不是將 sql_test~0 插入到虛擬表中,以下:

(將concat((SELECT database()),"~",floor(rand()*2)) 以a爲別名,方便做圖)

1547710722191

因爲虛擬表沒有內容,因此會將其插入到虛擬表中,這裏的插入過程當中,因爲插入的是a語句的結果,因此在插入時a語句中的rand()函數會再次執行,即插入的值可能爲sql_test~0 也可能爲 sql_test~1 ,這裏假設插入時a執行的結果爲sql_test~0

1547711441161

因此上面的狀況就是用sql_test~1這個結果查詢虛擬表,不存在該數據,因而插入虛擬表,插入時又運算一次,而後插入的值變成了sql_test~0,因此這就是主要的衝突,表中只有一條數據還好,即便查詢虛擬表的值和插入虛擬表的值不是同一個,但虛擬表也只生成一條記錄,不會出現問題。

然而當表的數據出現兩條以上的時候,第group by 在處理完第一條數據後會往下繼續處理第二條,因而第二條還會按第一條的處理方式進行:

1547712230675

因而就會報錯,報錯內容以下:

ERROR 1062 (23000): Duplicate entry 'sql_test~0' for key 'group_key'

1547712349931

若是第二次查詢和插入的結果都一致:就會有下面兩種狀況:

  • 都是sql_test~0:表裏已存在,該主鍵的count(*)值+1

  • 都是sql_test~1:表裏沒有,插入造成新的主鍵

1547713202940

部份內容轉載:https://www.cnblogs.com/laoxiajiadeyun/p/10283251.html

相關文章
相關標籤/搜索