这篇文章记录并分析介绍一些我遇到SQL注入方法。
大多数的SQL注入例子都来自sqli-labs。我的解题思路都在这里
双查询注入
sql-labs的这道题是Less-5 Double Query- Single Quotes- String
,解题过程在这里。
简单说就是通过双查询,利用数据库的报错信息来进行注入。
首先要注意几个函数:
1 | Rand() //随机函数 |
当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。
SELECT concat('string1','string2');
用concat()只是为了将之后报错的结果更好的显示出来,结合后面的group by分类。
concat(‘string1’,’string2’) |
---|
string1string2 |
Select rand();
函数返回大于0,小于1之间的数
rand() |
---|
0.674872587132149 |
select floor(3.14159)
floor向下取整
floor(3.14159) |
---|
3 |
我们组合随机和取整函数,即SELECT floor(rand()*2);
查询的结果只能是1或0
那我们执行SELECT CONCAT((SELECT database()), FLOOR(RAND()*2));
那么结果就会有两种可能,security0或security1。(以sqli-labs数据库为例)
执行SELECT CONCAT((SELECT database()), FLOOR(RAND()*2)) as 'users' from users;
结果为:
users |
---|
security0 |
security0 |
security1 |
security1 |
security1 |
security1 |
security0 |
security1 |
security0 |
security1 |
security0 |
security0 |
security0 |
此时如果懂SQL语句的话,这其实就说明了users这个表里有13条数据。
一些研究人员发现,使用group by子句结合rand()函数以及像count(*)
这样的聚合函数,在SQL查询时会出现错误,这种错误是随机产生的,这就产生了双重查询注入。使用floor()函数只是为了将查询结果分类。具体怎么做呢?
执行select concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
结果显而易见,只有两条,即两个分组security0和security1。
但是如果执行这条语句(加一个count(*)):
select count(*), concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
这个语句查询几次会有一定的概率爆出Duplicate entry
错误。
1 | 1062 - Duplicate entry 'security0' for key 'group_key' |
是不是发现什么了?对,数据库名爆出来了,在报错信息里。
通过floor报错的方法来爆数据的本质是group by语句的报错。group by语句报错的原因是floor(random(0)*2)的不确定性,即可能为0也可能为1(group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中则更新临时表中的数据;如果该key不存在于临时表中,则在临时表中插入key所在行的数据。group by floor(random(0)*2)出错的原因是key是个随机数,检测临时表中key是否存在时计算了一下floor(random(0)*2)可能为0,如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。
Ref: https://www.jianshu.com/p/e097a1c0d9ef / https://www.cnblogs.com/BloodZero/p/4660971.html
简单来说,为什么键值会重复呢,就是因为concat函数执行了两次,因为concat是连接两个随机字符串,当第二次执行的时候,有可能会出现与第一次键值重复的情况!那么这种情况下,就会报错!
使用聚合函数,group by子句,并利用随机函数产生错误运行时,由于涉及的随机函数和聚合函数计算;当在一个聚合函数,比如count后面如果使用分组语句就会把查询的一部分以错误形式显示出来;因为concat函数执行两次,比如select database(),这样就执行了两次select database,与后面的随机函数链接在一起,可能会随机重复,就会报错;
盲注
基于布尔的盲注
具体可见sqli-labs的[Less-8]