目录
1. SQL盲注
在进行SQL注入过程中,如果当前页面没有报错回显,并且也没有位置回显数据库返回结果的情况下,可以使用SQL盲注的方式对数据库中的内容进行猜解,盲注类型主要分为:布尔盲注和时间盲注。
当web页面只返回真假(true或false)两种不同类型的结果情况下,利用页面返回的不同类型结果逐个猜解数据就可以使用布尔盲注,如果web页面不返回true或false类型的结果,则可以使用时间注入。
真实的注入环境中,web页面肯定不会直接回显true或false的,一般根据页面返回的结果作为依据来判断。
2. 布尔盲注
例如:?id=1' and 1=1 --+ ,测试结果如下:
如果当前页面返回了结果,说明布尔盲注的条件为真(true)。
反之,布尔盲注的条件为假(false):
通常数据库正确执行SQL语句时,web页面并不会返回信息到页面:
在这条SQL语句中 ?id=1' union select 1,database(),3--+ ,数据库在执行SQL语句查询数据库名时,web页面不会直接返回数据库名字,可以使用ascii函数的方式以SQL执行后返回到web页面的结果来判断要查询的内容对应的ascii码是否正确。
ascii()函数:ascii码是美国信息交换标准代码,可以将字母转换为对应的数字形式的ascii码。
select ascii('a');语句的作用就是将字母a转换为对应的ascii码,也就是97。
例如,构造SQL语句:?id=1' and ascii('a') ==97--+ ,页面返回结果:
构造SQL语句:?id=1' and ascii('a') ==99--+ ,页面返回结果:
很明显,字母a的ascii码不是99,因此数据库执行SQL语句的结果是false,页面不回显任何结果。
由于页面是不回显命令查询的结果,当我们想要获取当前使用的数据库时,select ascii(select database())每次只能显示一个字母对应的数字,可使用substring函数来实现截取字母:
select ascii(substring((select database()),1,1));
substring函数主要是用于截取字符串的,有三个参数,第一个参数是要截取的字符串,第二个参数是截取字符的起始位置,第三个参数是截取字符的个数。
获取数据库名字时,通过substring函数和大于号和小于号来猜解字母的ascii码,字母‘a’到‘z’的ascii码值的范围是97 - 122,利用二分法的原则来对查找的数据库名字进行猜解。英文字母的区间范围是97 - 122,去中值就是112,在之后的字符猜解过程中,我们每次可以使用二分法取中值进行猜解:
第一次猜解:
Web页面返回true,说明第一个字符的ascii码值是大于112的。
再次对112到122之间取中值,进行第二次猜解:
我们发现第一个字符是不大于115的,那么我们猜测第一个字符是等于或小于115。
第三次猜解:
页面返回了true,说明第一个字符的ascii码值就是115,而115对应的字母就是字符‘s’,剩下的字符以此类推,修改substring函数的参数然后用二分法猜解出数据库的名字。
在真正的注入过程中,构造SQL语句如下:
#limit 0,1表示从第0行开始显示一行数据
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100--+
3. 如何判断布尔盲注的闭合方式
在判断布尔盲注的闭合方式时,和其他注入方式还是有所区别的:
4. 时间盲注
布尔盲注通过web页面返回真假(true或false)两种不同类型的结果来进行判断,拿到想要的信息。但有时候web页面可能只返回一个正常的页面,没有其他的错误信息可以反馈。
时间盲注就是,判断闭合方式的时候,无论提交任何数据,web页面只返回一个正常页面,利用页面响应时间不同,逐个猜解数据,使用场景一般是数据库会正常执行命令,不反馈页面信息。
举个例子:
在这个示例中无论如何构造SQL语句,web页面始终只返回一个正常的页面,这种情况一般是无法单独通过布尔注入进行判断,还需要使用到时间盲注方式。
时间盲注主要使用到两个函数,sleep函数和if函数。
sleep函数顾名思义,就是休眠的意思,参数以秒为单位,也可以为小数,使用方式如下所示:
sleep函数的参数可以为整数,也可以为小数,sleep(3.14)表示数据库执行命令查询到结果后,会休眠3.14秒再返回结果。
if函数,学过编程语言的同学肯定知道if在编程语言中是一个条件判断语句,有三个参数:
if(condition , true , false)
- condition参数表示if语句判断的条件
- true参数表示当condition条件为真时返回的值
- false参数则表示condition条件为假时返回的值
再来举个栗子:
分析:if(1=1,sleep(3),sleep(0))SQL语句,条件1=1的结果为真,接着就执行sleep(3)动作,休眠3秒后再返回结果。如果把条件修改为1=2,则条件1=2为假,执行sleep(0)动作,休眠0秒返回结果。
还记得SQLi-LABS的第9关吗,无论如何构造SQL语句页面都没有反馈信息,更无法判断出当前web页面的注入类型和闭合方式,那么我们可以采用布尔注入加时间注入方式了:
构造的命令是?id=1' and sleep(2)--+,从页面的执行结果来看,确实等待了2秒才把结果返回,也就是说and关键字后面的sleep(2)语句确实是被执行了,由此我们可以确定当前页面的注入方式了。
布尔注入加时间注入,构造SQL语句:
select if((ascii(substr((select database()),1,1))>112),sleep(3),sleep(0));
if语句中的条件为(ascii(substr((select database()),1,1))>112),当条件为真时,数据库执行命令查询到结果后,会等待3秒再返回结果,利用布尔注入中的二分法可以猜解出第一个字符是s,以此类推,按照这种方式就可以获取到完整的数据库名字,表名等信息。
判断数据库名字的长度:
if(length(database())=8,sleep(5),1)
使用二分法查询判断数据库表名:
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 100,sleep(3),sleep(0)) --+
同理,二分法来查询列名也可以参考查询数据库表名的方法。
时间盲注闭合方式的判断方法:
5. 总结
SQL盲注小结:
布尔盲注是在web页面只返回真假(true或false)两种不同类型的结果进行判断,从而猜解出想要的信息。时间盲注是通过web页面执行数据库命令的时长来猜解出想要的信息,两种注入方式原理是相通的,但也各有优缺点,在真实的注入环境中通常两种注入方式相互配合灵活使用。