前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你真的懂floor报错注入嘛

你真的懂floor报错注入嘛

作者头像
用户2700375
发布2022-06-09 14:40:27
9450
发布2022-06-09 14:40:27
举报
文章被收录于专栏:很菜的web狗很菜的web狗

好久好久没写博客了。。最近忽略了学习安全。今天抽时间回头重温了一下floor的报错注入,收获颇多

以前在研究SQL注入时只理解表面却不得精髓,很多原理都是一知半解。所以才有了本篇。。

一般的floor的报错语句为

代码语言:javascript
复制
select count(*) from user group by concat(database(),floor(rand(0)*2));

那么他是怎样报错 如何报错的?

报错函数分析

image-20201104143929317
image-20201104143929317

这个报错的意思就是它说group_key的主键test1重复了

可以看到爆出数据库名test1但是我的数据库名是test 那么这个1是哪里来的

1是来自floor(rand(0)*2)的。

rand

rand()是一个函数 这个函数在0和1之间产生一个随机数

而它后面的*2 ,则是选定获取数据的范围[0,2],其实就是乘以2。

image-20201104111614914
image-20201104111614914

rand(n)这个n是种子值 每个种子产生的序列是不一样的

image-20201104112755685
image-20201104112755685

floor

floor(n)这个函数的功能时返回不大于n的整数,比如

image-20201104113402183
image-20201104113402183

floor(rand(0)*2)这样组合起来的话就会必定返回0或者1其中一个了

image-20201104113723911
image-20201104113723911

concat

concat()是字符串拼接函数

返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。

image-20201104114409776
image-20201104114409776

count和group by

count(*)这个函数我一直给他理解为统计返回数值的函数.

image-20201104114752509
image-20201104114752509

例如这个,表示user表下面会返回五条数值。

group by是分组。需要和count连用

image-20201104140449425
image-20201104140449425

group by在执行时,会依次取出查询表中的记录并创建一个临时表,group by的对象便是该临时表的主键。如果临时表中已经存在该主键,则将值加1,如果不存在,则将该主键插入到临时表中,注意是插入!s

具体是怎样一个过程呢

username是admin发现表中没有这个主键,则将admin插入到主键 然后count(*)记为1。

接着取第二条记录。第二条记录发现admin已经作为主键了所以直接讲count(*)加1最终结果为

key

count(*)

admin

5

root

2

test

3

再探payload

这回我们回来看这个报错注入的payload

代码语言:javascript
复制
select count(*) from user group by concat(database(),floor(rand(0)*2));

报错语句就是 select count(*) from user group by test0或者select count(*) from user group by test1

下图是 用0先初始化种子,然后以这个种子初始化随机数(每次执行这个的结果都是一样的)

image-20201104150027460
image-20201104150027460

group by创建临时表的时候过程是这样的 因为第一个是test0,第二个是test1 ,参考上图

key

Count(*)

test0

1

test1

1

最终结果应该是

key

count(*)

test0

4

test1

6

那么为什么不是这个结果而是会报错 爆出

代码语言:javascript
复制
ERROR 1062 (23000): Duplicate entry 'test1' for key '<group_key>'

因为还有一个最重要的特性,就是group by与rand()使用时,如果临时表中没有该主键,则在插入前rand()会再计算一次。

当group by取第一条from记录时,group by的结果是 test0发现临时表中并没有test0这个主键,这个时候rand(0)*2会再算一次然后floor()后得到test1率先插入临时表的主键不是test0,而是test1,并计数1。

然后取第二条记录group by中的0,1仍然由floor(rand(0)*2)计算获得,第二次得到的数是1,也就是,第二条记录得到的是test1。因为此时临时表里已经有test1了,所以count(*)直接加1就可以了。

第几条

key

count(*)

Floor(rand(0)*2)

第一条

0

第一条

test1

1

1

第二条

test1

2

1

继续从from表中继续取下一条数据,再次计算floor(rand(0)2),结果为0,与database()拼接为test0

因为临时表的主键中并不存在test0,在插入前,floor(rand(0)*2)又计算一次,拼接后与test1,但是是直接插入,即使临时表中已经有了主键test1也硬要插入,从而导致主键重复报错

代码语言:javascript
复制
ERROR 1062 (23000): Duplicate entry 'test1' for key '<group_key>'

优化

网上大部分文章都说必须要有三条记录以上才可以报错。

因为上面共从from的表中取了三条记录,因为floor(rand(0)*2)的值为011011…,但其实第三次计算的1可以不要的,如果某个floor(rand(x)*2)满足0101或1010,那么from的表中两条数据就是可以报错的。

经测试floor(rand(14)*2)的序列为1010……..

也就是说 如果我们用floor(rand(14)*2)去尝试报错注入表里只要有两条数据以上就可以成功触发报错。这里我们尝试一下

image-20201104154009413
image-20201104154009413

总结

总结一下就是floor会报错的原因就是group by在向临时表插入数据时,插入重复主键导致的报错,又因为报错之前concat()里的database()语句已经执行过了所以说,会直接爆出concat函数里执行后的结果

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 报错函数分析
    • rand
      • floor
        • concat
          • count和group by
          • 再探payload
          • 优化
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档