vlambda博客
学习文章列表

Sql注入-6:布尔注入(上)


引言

sql注入-6

之前介绍了基于报错和回显的注入,但一般的网站不会打开sql出错信息显示,或者有些时候并不会有回显结果,这时候就需要使用盲注,盲注分为很多种,本节先介绍基于布尔的盲注。

函数介绍

sql注入-6

首先介绍几个盲注中会用到的函数:


01

left(str,len)

从左往右截取指定长度的字符串,str为接收的字符串,len为截取的长度。

示例:left('Hello World',3)结果为'Hel'


02

substr(str,pos,len)

从起始位置截取指定长度的字符串,str为接收的字符串,pos为起始位置,len为长度。

示例:substr('Hello World',2, 3)结果为'ell'。

注:mysql中mid(str,pos,len)函数与其类似。


03

 ascii(str)

返回字符串中第一位的ascii值,str为接收的字符串。

示例:ascii('hello')结果为104,因为h的ascii值为104。

注:ord(str)函数与其类似。


04

regexp正则表达式

regexp根据后面指定的正则表达式对结果进行筛选。

示例:select * from users where username regexp '^[a-d]'这一语句中从users表中查询所有username字段值以a或b或c或d字符开头的所有信息。

注:正则表达式的匹配字符串有很多方式,内容也很多,可以查询资料学习,这里就不多赘述了。


05

like模糊匹配

like根据后面指定的匹配字符串对结果进行筛选。

示例:select * from users where username like '%um%'这一语句中从users表中查询所有username字段值包含um字符的所有信息。


06

length(str)

返回字符串的长度,str为接收的字符串。

示例:length('Hello')结果为5。

布尔盲注

sql注入-6

盲注以sqli-labs的less-8为例,首先看到正确提交id后,查询出了Dumb的信息页面,但本页面没有显示Dumb的信息,而是显示了“You are in...........”。

    同时在故意构造错误的sql语句后,页面也没有回显错误,只是显示了一个空的页面,并当查询不到信息时也返回了空的页面。

Sql注入-6:布尔注入(上)

    这时候即使我们发现了注入点,也拿不到数据库内的任何信息,这就需要靠盲注了,根据上面的例子,我们可以知道当网页正确查询了某一记录后,会返回一个查询正确的页面,当查询不到的时候,会返回另一个页面,找到不同情况下两种页面的显示结果是布尔盲注的关键。现在我们构造这样一个payload:

?id=1' and left(database(),1)="a" --+

    上面语句中的单引号闭合sql正常的查询,然后跟了and逻辑运算,只有当后面的运算结果正确,才会使得整个语句查询成功,若查询成功,则显示you are in的页面,否则返回空页面,而这语句查询成功的关键就在于数据库名的第一位是不是a,因此我们可以通过一个个字符尝试,直到找到正确的第一个字符,当字符为a时,页面返回空。(注:构造payload时字符串的引号与闭合的引号区分开,避免冲突,如这里的a字符使用双引号)

Sql注入-6:布尔注入(上)

    于是我们一个个尝试,直到尝试s字符时,发现页面返回正常,这也就说明数据库的第一个字符肯定是s。

Sql注入-6:布尔注入(上)

    那么接下来尝试第二位进行盲注,使用left(database(),2)=”sa”,通过第二位字符的遍历获得答案。现在就有一个问题了:我们怎么知道数据库名到底有几位呢?因此在第一位字符盲注之前,我们需要使用length函数对数据库的长度进行盲注,从1一直往上尝试,直到8返回正确的界面,构造的payload如下:

?id=1' and length(database())=8 --+
Sql注入-6:布尔注入(上)

    所以到这里我们就知道数据库名的长度为8,从而盲注到第8位就可以停止了,最后通过盲注拿到了数据库名称为security,最后一次盲注的payload如下:

?id=1' and left(database(),8)="security" --+
Sql注入-6:布尔注入(上)

    至于其他的数据库信息,都可以通过这种思路进行盲注获取,这就是基本的布尔盲注。


使用正则表达式

sql注入-6

这一次我们使用正则表达式来进行布尔盲注,同时获取security数据库的全部表名,首先构造这样一个payload:

?id=1' and 1=(select 1 from information_schema.TABLES where table_schema="security" and table_name regexp "^u") --+

    分析一下这一payload,从mysql自带数据库中查询security数据库中所有以u字符开头的表,查询到的结果以1返回,若能查询到,则1=1返回true,因此总的查询id=1成功,返回正确的界面,security数据库中确实存在以u开头的表名,但是我们发现返回了空页面。

Sql注入-6:布尔注入(上)

    这是因为security中存在users和uagents两张以u开头的表,因此会查询出一个表结构,里面有两个1,而这个结果与1进行等于比较会出现语法错误,而页面隐藏了报错信息,因此返回了空页面,所以在使用正则表达式进行盲注的时候,切记要在后面加上limit 0,1,只返回一条记录,更新后的payload如下:

?id=1' and 1=(select 1 from information_schema.TABLES where table_schema="security" and table_name regexp "^u" limit 0,1) --+

    盲注的方式同第三节一样,详细的盲注过程见下表:

正则表达式

页面返回结果

判断结果

^u

You are in

存在以u开头的表名

^ua

You are in

存在以ua开头的表名

^us

You are in

存在以us开头的表名

^uag

You are in

存在以uag开头的表名

^uage

You are in

存在以uage开头的表名

^uagen

You are in

存在以uagen开头的表名

^uagent

You are in

存在以uagent开头的表名

^uagents

You are in

存在以uagents开头的表名

^uagents[a-z]

空页面

确认存在一个表uagents

^use

You are in

存在以use开头的表名

^user

You are in

存在以user开头的表名

^users

You are in

存在以users开头的表名

^users[a-z]

空页面

确认存在一个表users

    上表中当遍历到ua和us都成功,因此存在两个表,先遍历ua,再遍历us,当uagents遍历后再进行一位的遍历,发现页面均没有正确结果,因此确定表名就是uagents,也可以先判断表名的长度再遍历盲注,users表同理。(上表中红色为盲注uagents表,蓝色为盲注users表)

Sql注入-6:布尔注入(上)
Sql注入-6:布尔注入(上)

 小结

sql注入-6

    本节介绍了布尔盲注的基本原理,同时用手工的方式完成了布尔盲注,但是在真实的渗透测试中,手工一次次的尝试显然是不现实的,因此需要借助自动化工具的帮助,我们可以在找到注入点后使用sqlmap进行扫描,所有的结果就一目了然了,但是在学习过程中应先了解原理,因此在下一节会使用python编写一个布尔盲注的自动化检测工具,从代码中深入感受盲注的过程。

感谢观看,理解有误之处,欢迎交流和指导!

刘杰寅

知乎|烈焰宝宝