SQL布尔盲注 (Blind)基本原理及使用burpsuite进行暴力猜解 NewStarCTF2023week4-midsql(利用二分查找实现时间盲注攻击)

SQL布尔型盲注入是一种SQL注入攻击方式, 根据某个条件是否成立,来判断返回结果的真假,通过布尔型盲注,攻击者可以逐个字符地推断出数据库中存储的信息,如用户名、密码等,从而获取敏感信息或者执行非法操作。

什么情况下我们会采用盲注?我们平时最常用的是union联合查询注入,这是基于页面有数据回显的条件;但是,如果无论你输入什么,页面始终都只回显两种情况,我们可以把这两种情况看成是1或者0,也就是说,要么你查的东西有,要么不存在。

面对这种只回显两种情况的,我们一般是采用盲注。盲注可以分为时间延迟盲注和布尔型盲注两种,时间延迟盲注是利用时间延迟等待的方式进行推断(主要使用sleep函数),而布尔型盲注则是利用返回结果的布尔值(1或0)进行推断(主要使用substring()、length()函数)。两种盲注都还会用到if()函数进行条件判断。

关于时间盲注及sleep函数的用法,参考我之前的博客:

NewStarCTF2023week4-midsql(利用二分查找实现时间盲注攻击)

http://t.csdnimg.cn/qwz4B

本篇博客主要介绍布尔盲注

length()函数用于判断长度,重要的是substring()函数,该函数用于字符串截取,共有三个参数:

substring(database(),x,y)

其中database()可以可以理解为一个字符串,因为该函数会回显数据库名,对吧,因此第一个参数其实就是我们得到的一个字符串;

第二个参数x,表示截取字符串的起始位置,也就是说控制从第几个字符开始截取;

第三个参数y,用于控制截取出几个字符。

这里我们使用 dvwa 靶场给大家讲解和演示

注意:难度选成low,你要是选的impossible那就没得玩了

来到 SQL injection(blind)

输入存在的id,比如1

回显情况一:User ID exists in the database.

输入不存在的id

回显情况二:User ID is MISSING from the database.

这里就算输入1'也不会回显SQL语句报错界面,依旧是回显情况二。

这里会有一个url编码的问题,因此我们直接在url修改id的内容

首先判断是否存在布尔盲注

(准确来说我们是应该先找闭合点,一般是单引号或者双引号的字符型或者数字型)

1' and if(1=1,1,0)--+

使用单引号将前面的查询语句闭合,and后面继续执行if语句 ;

if(1=1,1,0)表示:如果1=1,则返回1,否则返回0;

最后再使用 --+ 将后面内容注释掉(常见的注释还有#)。

可以看到页面回显正常:User ID exists in the database.

1' and if(1=2,1,0)--+

1显然不等于2,则返回0

页面回显查询内容不存在:User ID is MISSING from the database.

换句话说,页面回显的情况只有真和假,即0和1,这显然符合盲注的条件;并且回显内容不包含数据库里内容的任何信息,显然联合查询是无法实现查询的,只能采用盲注。

我们可以先看一下这个靶场的数据库内容,主要是便于大家理解我后面给出的注入语句。

数据库名:dvwa

表名:guestbook、users

列名:...

这里先给大家看了内容我们进行判断,之后我会讲在不知道的情况下使用burpsuite进行猜解。

1' and if(substring(database(),1,1)='d',1,0)--+

判断数据库名的第一个字符是否为'd',是则返回1,否则返回0。 

通过回显结果我们可以得知数据库名第一个字符为'd'。

1' and if(substring(database(),1,1)='a',1,0)--+

 判断数据库名的第一个字符是否为'a',是则返回1,否则返回0。 

通过回显结果我们可以得知数据库名第一个字符不是为'a'。

基于上述原理,如果我们将所有大小写字母和数字以及特殊字符都遍历一遍,理论上来说是不是就可以爆出数据库名了呢?

那么我们第一步其实是先判断数据库名的长度:

1' and if(length(database())=4,1,0)--+

如果数据库名的长度是4个字符,则返回1,否则返回0。

通过回显信息可以得到数据库名长度就是4个字符

1' and if(length(database())=6,1,0)--+

如果数据库名的长度是6个字符,则返回1,否则返回0。 

通过回显信息可以得到数据库名长度不是6个字符

上述都是一些简单的测试语句,接下来我们使用burpsuite进行爆破猜解。

比如我们先爆破数据库名的正确长度

我们首先也提交上述注入语句

1' and if(length(database())=6,1,0)--+

使用bp抓包,抓到后发给攻击模块(还是需要注意URL编码的问题)

请求时依旧在URL直接改变id的值,然后使用bp拦截,拦截后内容如下图:

如果分号没有被转成%27,空格没有被转成%20,可能会报400的错误。

设置参数位置

这里只爆一个参数,因此使用狙击手(也可以同时爆破两个参数则需要使用其他攻击类型)

使用一个简单的自带字典

设置好后开始攻击

通过结果我们可以一眼得出,数据库名长度为4个字符串。

接下来我们爆破具体的数据库名

1' and if(substring(database(),1,1)='a',1,0)--+

这里的变量有两个:

第一个参数用于决定数据库名字符串的截取位置;

(我们已经知道数据库名长度为4)

第二个参数用于判断截取出来的这个字符的具体内容。

(使用包含所有大小写字母数字特殊字符的字典)

由于存在多个参数,并且位置和内容并不存在一一对应关系,我们需要的是所有可能的组合,因此攻击类型使用集束炸弹。

设置第一个参数爆破的字典,我们已经知道数据库名长度为4个字符,因此这里我们只需要分别截取第1、2、3、4个字符即可。

设置第二个参数的爆破字典

我这里添加了所有的大小写字母和数字

爆破结束

我们直接筛选状态码为200,即回显为真的结果

拼接字符得到数据库名为dvwa,因为我的靶场是Windows系统搭建的,因此对大小写不敏感。

(似乎mysql数据库默认对大小写不敏感,并且是可以进行设置和修改的)

接下来我们查该数据库(dvwa)下的表名

1' and if(substring((select table_name from information_schema.tables where table_schema='dvwa' limit 0,1),1,1)='a',1,0)--+

limit 0,1 表示从第一条数据开始取,共取出1条记录。

limit可用于猜解多条数据,再比如:limit 2,4 则表示取出第3条至第6条,共取4条记录。

设置攻击类型和爆破位置

这里我们没有提前测表名长度,因此可以将字典长度适当设长一点;

由前面经验我们知道大小写不敏感,因此这里我只放了小写字母和数字。

爆破完成,使用过滤器筛选出响应状态码为200的

按照payload1排序(因为我们是从表名第一个字符依次往后爆破的)

得到第一张表名为:guestbook

尝试获取第二张表名,按照我们前面讲的limit使用规则,将其修改为 limit 1,1

1' and if(substring((select table_name from information_schema.tables where table_schema='dvwa' limit 1,1),1,1)='a',1,0)--+

操作方法同上,即可爆出第二张表名为:users

接下来我们尝试爆破users表下的列名

1'and if(substring((select column_name from information_schema.columns where table_name='users' and table_schema='dvwa' limit 0,1),1,1)='a',1,0)--+

在设置爆破参数时我们可以多添加一个,即limit的第一个参数,用于控制从第几条记录开始取

如下图所示:

对于limit的第一个参数来说,它是从0起的,结尾我们设到10

(也就是说我们最多取到第11条数据)

对于substring的第二个参数,它是从1起的,我们也取至10

第三个参数则是爆破具体的列名,保险起见这里使用所有大小写字母数字和特殊字符

内容较多,耐心等待

爆破结束,第一个列名应该是:user_id

考虑到大小写的干扰,我们还是只使用小写字母再试一次

现在看着就很明显,依次往下为该表的第二、三...个列名

但是部分列名似乎顺序不太对,因为这里似乎只能按照一个payload的顺序排,但我们也可以大致的看出单词字母的正确顺序,如果想更加准确明显的精准爆破,那么建议只指定一个或两个参数多次爆破,参数太多,结果顺序显示就容易出问题。

我们可以看到这里有一个名为password的列,那么我们尝试获取该列的具体字段数据

即查询数据库名为dvwa,表名为users,列名为password下的具体字段内容

1' and if(substring((select password from dvwa.users limit 0,1),1,1)='a',1,0)--+

但是我们首先还是先判断一下密码的长度

1' and if((select length(password) from dvwa.users limit 0,1)=1,1,0)--+

使用狙击手爆破单个参数

得到密码password的长度为32

使用上述payload获取密码具体内容

1' and if(substring((select password from dvwa.users limit 0,1),1,1)='a',1,0)--+

设置参数位置,选择攻击类型

第一个参数字典非常明确1-32

因为我们知道密码长度为32,并且我们需要爆破出每一位的具体值

第二个参数使用所有字母数字特殊字符

筛选结果时发现还是存在大小写不敏感的问题,因此字典依旧不使用大写字母

但是这里排序出来的密码password顺序不太对,我们保存攻击结果

只保存payload1和payload2

我们需要按照payload1的顺序来排序

最终整理得到密码password:5f4dcc3b5aa765d61d8327deb882cf99

与数据库内容一致

至此,我们实现了基于布尔盲注爆破数据库名、表名、列名以及具体字段信息。

后续会继续给大家更新网络安全、Web漏洞、CTF相关的文章。

创作不易,期待大家的支持与关注!

相关推荐

  1. SQL注入攻击 - 基于时间

    2023-12-25 03:46:02       44 阅读
  2. 布尔+时间+堆叠注入

    2023-12-25 03:46:02       22 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-25 03:46:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-25 03:46:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-25 03:46:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-25 03:46:02       18 阅读

热门阅读

  1. go从0到1项目实战体系二十三:GORM

    2023-12-25 03:46:02       23 阅读
  2. C语言使用qsort和bsearch实现二分查找

    2023-12-25 03:46:02       39 阅读
  3. C++:第十讲二分查找

    2023-12-25 03:46:02       39 阅读
  4. 7-2 非递归二路归并排序

    2023-12-25 03:46:02       36 阅读
  5. 超酷的爬虫可视化界面

    2023-12-25 03:46:02       36 阅读
  6. C#字典和列表转LuaTable

    2023-12-25 03:46:02       36 阅读
  7. LeeCode前端算法基础100题(15)-最大子数组和

    2023-12-25 03:46:02       31 阅读
  8. leetcode203题目移除链表元素

    2023-12-25 03:46:02       32 阅读
  9. 【.NET Core】反射(Reflection)详解(二)

    2023-12-25 03:46:02       38 阅读