环境:win10
靶场:sqli-labs-master
本实验仅供学习参考!!!
1 布尔盲注
盲注就是在 SQL 注入过程中, SQL 语句执行后,查询到的数据不能 回显到前端页面。此时,我们需要利用一些方法进行判断或者尝 试,这个过程称之为盲注。而布尔盲注就是SQL 语句执行后,页面 不返回具体数据,数据库只返回0 或者 1 (真 or 假)。 类似于无法开口说话的人,只能通过点头和摇头来告诉你答案的正 确与否。
1.1 布尔盲注的特性
在页面中,如果正确执行了用户构造的 SQL 语句,则返回一种页 面,如果 SQL 语句执行错误,则执行另一种页面。基于两种页面, 来判断 SQL 语句正确与否,达到获取数据的目的。
正常的页面:
查询不到的页面:
1.2 布尔盲注的基本流程
1 、判断是否存在注入:sql注入必须的过程
2 、获取数据库长度:因为盲注无法回显数据,所以我们需要猜数据库名的长度,为下一步猜测数据库名做准备。
3 、逐字猜解数据库名
4 、猜解表名数量
5 、猜解某个表名长度
6 、逐字猜解表名
7 、猜解列名数量
8 、猜解某个列名长度
9 、逐字猜解列名
10、判断数据数量
11 、猜解某条数据长度
12 、逐位猜解数据
2. 攻击过程
2.1 判断是否存在注入
第一步:正常查询,返回 True (语句执行成功)或者返回 False (语 句执行成功没有查询到内容)
第二步:输入引号进行看页面变化,页面返回 False ,可能存在漏 洞,也可能没有查询到内容
第三步:利用 and 进行判断,比如: 1 and 1=1 和 1 and 1=2 , 1’ and 1=1#和 1’ and 1=2# ,如果前者执行的结果不一样,说明是数字型的 布尔盲注,如果后者执行的结果不一样,说明是字符型的布尔盲 注。
输入 1 后发现页面显示 You are in。。。。似乎是正常显示
输入 1' 发现页面没有任何变化,我判断是存在漏洞
接下来判断注入类型
发现输入 1 and 1=1 和 1 and 1=2 的结果一样很明显不符合数字类型(这里之所以一样是因为这里是字符型,查询语句将输入内容看为整体,那么就涉及到了隐式类型转换,最终转换结果这连个语句都是1,所以都是正确结果) ,那么就是字符型了
判断闭合类型
1' and 1=1--+和 1' and 1=2--+分别为正常显示,无反应(也就是单引号没有闭合)
判断出是单引号闭合,这里为什么这样判断上面有说,我的上一篇文章也有讲为什么 http://t.csdnimg.cn/wRLmq。这里也判断出单引号闭合了,且这个靶场没有回显数据,所以我们不能判断回显位了,我们需要另一种方式
2.2 获取数据库长度
因为无法通过页面数据回显获取数据,所以只能靠判断对错的方式 来获取数据,可以使用MySQL 中内置的 length() 函数获取长度 。
length() 是一个用来获取字符串长度的内置函数。
char_length() :在 mysql 内置函数里面查看字符串长度的还有一个函数是char_length() 。
这两个函数的区别是:
a )、 length() : 单位是字节, utf8 编码下 , 一个汉字三个字 节,一个数字或字母一个字节。gbk 编码下 , 一个汉字两个字节,一个数字或字母一个字节。
b )、 char_length() :单位为字符,不管汉字还是数字或者是 字母都算是一个字符。
使用length()函数计算长度,我猜是8个字节,猜中页面正常显示
如果不想一个一个试,可以用 '>' '<' 来缩小范围,然后在试
1' and length(database())<10
1' and length(database())>5
从上面两次判断,就将长度范围缩小了。接下来就要开始逐个猜数据库
2.3 获取数据库名
从上个步骤中获取到数据库长度之后,接下来就是获取名字,如何 获取呢?可以通过截取字符串的方式进行获取。
substr(string, start, length) 截取字符串,注意, mysql 中的 start 从1 开始的。这个函数的意思简单来说,截取一个字符串从'start'位,可以是第1位,第2位。。。。每次截取'length'个字符。
1' and substr(database(),1,1)='s'--+(从第一位开始,截取一个字符)我猜到了' s'是第一个字符(一个一个试),显然这种方式非常浪费时间。那么我们需要另一种方式,快速的能够确定答案
使用。
我使用了ascii()函数。其作用是将字符转换成对应的ascii值(数字),那么我们就可以利用 > <
来缩小范围然后再猜。
1' and ascii(substr(database(),1,1))>97--+
1' and ascii(substr(database(),1,1))<110--+
后续我就不再继续缩小。我直接使用最简便的方法。
BurpSuite,爆破密码(同样可以用来破解我们这种情况)
抓包后发送给Intruder
选择第四个破解方式
需要改变的两个分别是字符开始的位置和我们猜测的ascii码值
因为这两个都是数值所以我们选择Payload type为:Numbers
第一个改变的地方相当于就是我们数据库的长度我们上面试出了为8,所以我们设置为1-8,步长为8
第二个改变的是ascii码值,范围可以设置为33-126
在获取数据库名的时候注意数据库的命名规则,他是采用 26 个英文 字母( 区分大小写 ) 和 0-9 的自然数 ( 经常不需要 ) 加上下划线 '_' 组成, 命名简洁明确,多个单词用下划线'_'分隔。 为了避免有些人不按照命名规则命名,可以对 ascii 码值 33 到 126 进行遍历枚举。
然后开始攻击
攻击完后点击length进行排序,能真正成功的都与大部分结果显示不一样,很明显这8条正是我们要的结果,再将ascii码转换为对应的字符就是我们的数据库名(要按照顺序来id:1-8)
为了更严谨我们可以以次选中这8条查看响应包内容
观察到和我们在HackBar中输入正确查询后显示的一样
还有更更直观的如图
那么数据库名为security
2.4.获取表的数量
但是由于无法看到有多少个表,为了避免无效查询,所以可以先获 取表的数量,可以使用count() 函数进行获取, count() 统计数据表中包含的记录行的总数,或者根据查询结果 返回列中包含的数据行
与之前sql注入查询语句一样只需要加上判断就可
1' and (select count(table_name) from information_schema.tables where table_schema='security')=4--+
2.5获取表的长度
1' and length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=6--+
这里我来解释一下这条语句首先是最内层查询语句这个很好理解就是查表,内存有一个limit 0,1这个代表从第0个开始(也就是我们认为的第一个表)截取1个。
然后内存查询语句作为整体放入到 length 函数中计算长度所以有两层括号(这里括号关系必须有两层,如果内层不加括号的话,因为limit后有逗号,这样lenrth函数会以为有两个参数这样就错了),我猜中了第一个表的长度。想要快速猜中每张表那么就用burpsuite进行爆破
limit后面跟着一个%20这个代表空格
我们将 第n个表和 表的长度分别加上标记对这两个位置进行爆破,使用Cluster bomb方式
前面我们计算出了有四张表
表名一般不会很长可以像我这样试一下不在这范围内可以再改
2.5获取表的长度
这四条分别对应四张表的长度
2.6获取表名
1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101--+
这里的括号关系同样也要搞清楚可以先将substr和内层查询语句括号关系搞清楚(同length函数),再写入到ascii函数内,这里我猜中了第一张表的第一个字符的ascii码值为101,也就是 e, 想要快速得出几张表的名字还是同样的方法使用burpsuite
第一张表名为:emails ,想要得出其他几张表要将limit 0,1中第一个参数进行更改
然后根据每张表的长度来更改范围,再来爆破
第二张表名:referers
第三张表名:uagents
第四张表名:users
2.7获取表字段数
以emails表为例
1' and (select count(column_name) from information_schema.columns where table_schema='security' and table_name='emails')=2--+, 有两个字段
2.8获取字段长度
length((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1))=2--+
1' and length((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 1,1))=8--+
第一个字段长为2,第二个为8。这里获取字段长度和上面获取表名长度一个道理
2.9获取字段名
这里我就不猜了直接burpsuite爆破
1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),1,1))=105--+
第一个字段:id
第二个字段名:email_id
2.10获取数据条数
1' and (select count(id) from emails)=8--+
猜中有八条数据
2.11获取数据
1' and ascii(substr((select group_concat(id) from emails),1,1))=49--+
直接burpsuite爆破,注意这里用了group_concat函数,是数据在同一行显示中间会用逗号隔开,再爆破时相当于15条数据
数据分别为1,2,3,4,5,6,7,8,到这里数据也查询出来了,需要其他数据方法一样。