温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

sql注入报错怎么解决

发布时间:2022-06-10 11:54:05 来源:亿速云 阅读:140 作者:iii 栏目:开发技术

今天小编给大家分享一下sql注入报错怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

0x01

我们先来看一看现象,我这里有一个users表,里面有五条数据:

sql注入报错怎么解决

然后用我们的报错语句查询一下:

select count(*),(concat(floor(rand()*2),(select version())))x from users group by x

sql注入报错怎么解决

成功爆出了数据库的版本号。

要理解这个错误产生的原因,我们首先要知道group by语句都做了什么。我们用一个studetn表来看一下:

sql注入报错怎么解决

现在我们通过年龄对这个表中的数据进行下分组:

sql注入报错怎么解决

形成了一个新的表是吧?你其实应该能够想到group by 语句的执行流程了吧?最开始我们看到的这张sage-count()表应该时空的,但是在group by语句执行过程中,一行一行的去扫描原始表的sage字段,如果sage在sage-count()不存在,那么就将他插入,并置count()置1,如果sage在sage-count()表中已经存在,那么就在原来的count(*)基础上加1,就这样直到扫描完整个表,就得到我们看到的这个表了。

注:这里有特别重要的一点,group by后面的字段时虚拟表的主键,也就是说它是不能重复的,这是后面报错成功的关键点,其实前面的报错语句我们已经可以窥见点端倪了

sql注入报错怎么解决

0x02

正如我前面所说的,报错的主要原因时虚拟表的主键重复了,那么我们就来看一下它到底是在哪里,什么时候重复的。这里rand()函数就登场了。
首先我们先来了解rand()函数的用法:

1.用来生成一个0~1的数

2.还可以给rand函数传一个参数作为rand()的种子,然后rand函数会依据这个种子进行随机生成。

那他们的区别是什么呢?我们来看一下,这两个语句的执行效果:

sql注入报错怎么解决

可以看到rand()生成的数据毫无规律,而rand(0)生成的数据则有规律可循,是:
0110 0110

注:如果你觉得数据不够,证明不了rand()的随机性,你可以自己多插入几条数据再查询试一下。

0x03

现在我们弄清楚了group by语句的工作流程,以及rand()与rand(0)的区别,那么接下来就是重点了,mysql官方说,在执行group by语句的时候,group by语句后面的字段会被运算两次。

**第一次:**我们之前不是说了会把group by后面的字段值拿到虚拟表中去对比吗,在对比之前肯定要知道group by后面字段的值,所以第一次的运算就发生在这里。

**第二次:**现在假设我们下一次扫描的字段的值没有在虚拟表中出现,也就是group by后面的字段的值在虚拟表中还不存在,那么我们就需要把它插入到虚拟表中,这里在插入时会进行第二次运算,由于rand函数存在一定的随机性,所以第二次运算的结果可能与第一次运算的结果不一致,但是这个运算的结果可能在虚拟表中已经存在了,那么这时的插入必然导致错误!

所以我们现在通过一个例子来验证我们的理论,拿出我们最开始的例子:

select count(*),(concat(floor(rand(0)*2),'@',(select version())))x from users group by x

声明:users表就是本文第一个表,表中有五条数据

注意我这里用的是rand(0),不是rand(),rand(0)生成的有规律的序列:

sql注入报错怎么解决

我们跟着刚刚的思路走,最开始的虚拟表是空的,就像下面一样:

当我扫描原始表的第一项时,第一次计算,floor(rand(0)*2)是0,然后和数据库的版本号(假设就是5.7.19)拼接,到虚拟表里去寻找x有没有x的值是x@5.7.19的数据项,结果显然是没有,那么接下来就将它插入到上表中,但是还记得吗,在插入之前会进行第二次计算,这时x的值就变成了1@5.7.19,所以虚拟表变成了下面这样:

count(*)x
11@5.7.19

现在扫描原始表的第二项,第一次计算x==’1@5.7.19‘,已经存在,不需要进行第二次计算,直接插入,得到下表:

count(*)x
21@5.7.19

扫描原始表的第三项,第一次计算x==‘0@5.7.19’,虚拟表中找不到,那么进行第二次计算,这时x==‘1@5.7.19’,然后插入,但是插入的时候问题就发生了,虚拟表中已经存在以1@5.7.19为主键的数据项了,插入失败,然后就报错了!

上面是使用rand(0)的情况,rand(0)是比较稳定的,所以每次执行都可以报错,但是如果使用rand()的话,因为它生成的序列是随机的嘛,所以并不是每次执行都会报错,下面是我的测试结果:

sql注入报错怎么解决

执行了五次,报错两次,所以是看运气。

以上就是“sql注入报错怎么解决”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

sql
AI