sql 从三个值中取随机数_渗透测试之SQL注入(四)

前文写的是boolean注入,今天来给师傅们写写报错注入。

一、什么是报错注入

顾名思义,报错注入就是通过页面爆出的错误信息,构造合适的语句来获取我们想要的数据,本章节讲述的注入,数据库为MySQL。

二、出现报错注入的原因

首先是应用系统未关闭数据库报错函数,对于一些SQL语句的错误,直接回显在了页面上,部分甚至直接泄露数据库名和表名;

其次,必不可少就是后台未对MySQL相应的报错函数进行过滤

三、集中常见的报错注入用到的函数

1.updatexml()

2.floor()

3.extractvalue()

4.exp()

但这里使用最为常见的还是updatexml()函数

四、updatexml()的使用方法

updatexml()的语法为

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

如果找不到相应的xpath路径,updatexml函数就会报出错误

concat()函数。此函数用于连接字符串;由于updatexml()函数xpath路径需要连接特殊字符,被连接的特殊字符需要进行16进制编码

concat_ws()函数。语法concat_ws(0x7e,database(),use()),会把查出来的库名和用户通过~连接起来完成报错

下面我门可以进入到sqli-lab的第五关

输入?id=1看看是什么个样子

08cceb08-8b39-eb11-8da9-e4434bdf6706.jpeg

出现了一个You are in.......的字样

那我们在后面再加一个单引号闭合看看出现什么

dc52dba55a59674509448334f91d2364.png

这里爆出了错误语句,这个时候我们就可以利用我们报错注入来进行注入了

我们可以利用如下的payload

?id=-1'union select count(*),count(*), concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+

这里就爆出了数据库名

df27f5dd2ec44e03d4f418c7e0853be4.png

接下来就是表名、字段名等,那么这个payload实现的原理是什么呢。

几个关键函数的说明

rand(0)*2

rand() 可以产生一个在0和1之间的随机数。c02c8b71c94d8a2836b4eadcab6f5268.png

可见,每次产生的都不一样。当我们提供一个种子参数 0 后,再次查看:7ee6342c6f1f703ac26e05018928685d.png

可以发现,每次产生的值都是一样的。也可以称之为伪随机(产生的数据都是可预知的)。
查看多个数据看一下。( test 是我之前创建的一个拥有9条数据的表)7ee6342c6f1f703ac26e05018928685d.png

发现第一条数据与刚才查看的单个数据相符合,其它的数据也完全一样。
为什么要乘以 2 呢?这就要配合 floor 函数来说了。

floor(rand(0)*2)

floor() 返回小于等于该值的最大整数。
之前我们了解到,rand() 是返回 0 到 1 之间的随机数,那么乘 2 后自然是返回 0 到 2 之间的随机数,再配合 floor() 就可以产生确定的两个数了。也就是 0 和 1。d80ac524857c212510373c520e551a87.png

为什么需要这两个数呢?

group by 与 count(*)

group by 主要用来对数据进行分组(相同的分为一组),这里与count() 结合使用。举个例子就一目了然了。d80ac524857c212510373c520e551a87.png

可以观察到,这里对重复性数据进行了整合,然后计数。

重点来了,也就是在这个整合然后计数的过程中,中间发生了什么我们是必须要明白的。
经过网上查询,发现mysql遇到该语句时会建立一个虚拟表。该虚拟表有两个字段,一个是分组的 key,一个是计数值 count(*)。也就对应于上个截图中的 prod_price 和 count(*)。
然后在查询数据的时候,首先查看该虚拟表中是否存在该分组,如果存在那么计数值加1,不存在则新建该分组。

报错分析

rand()的特殊性

select count(*) from test group by floor(rand(0)*2);

而又因为 rand 函数的特殊性(如果使用rand()的话,该值会被计算多次)。
在这里的意思就是,group by 进行分组时,floor(rand(0)*2)执行一次(查看分组是否存在),如果虚拟表中不存在该分组,那么在插入新分组的时候 floor(rand(0)*2)就又计算了一次。(其实在上述 rand(0) 产生多个数据的时候,也能观察出来。只要 rand(0) 被调用,一定会产生新值)。

这样,所有的理论细节就全部明朗了。

报错

还记得我们之前产生的疑问,为什么要用 floor(rand(0)*2产生 0 和 1 这两个数吗?3aa3d6b0537d1eaa22ccb2f677fb6b26.png

当 group by 对其进行分组的时候,首先遇到第一个值 0 ,发现 0 不存在,于是需要插入分组,就在这时,floor(rand(0)*2)再次被触发,生成第二个值 1 ,因此最终插入虚拟表的也就是第二个值 1 ;然后遇到第三个值 1 ,因为已经存在分组 1 了,就直接计数加1(这时1的计数变为2);遇到第四个值 0 的时候,发现 0 不存在,于是又需要插入新分组,然后floor(rand(0)*2)又被触发,生成第五个值 1 ,因此这时还是往虚拟表里插入分组 1 ,但是,分组 1 已经存在了!所以报错!30b9d3a5081b261a10e393d62b624571.png

总结

可见,floor(rand(0)*2的作用就是产生预知的数字序列01101,然后再利用 rand()的特殊性和group by的虚拟表,最终引起了报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值