前言
通过前面5期的代码审计,我们已经修复了这套系统的绝大部分漏洞,同时也学习到了不少知识。这一篇文章是这一个系列的最后一篇文章,接下来我将继续分析漏洞原理并讲解修复方法。
AKun Wallpaper 代码审计实战分析1:https://blog.csdn.net/rpsate/article/details/122354690
AKun Wallpaper 代码审计实战分析2:https://blog.csdn.net/rpsate/article/details/122387998
AKun Wallpaper 代码审计实战分析3:https://blog.csdn.net/rpsate/article/details/122400520
AKun Wallpaper 代码审计实战分析4:https://blog.csdn.net/rpsate/article/details/122417856
AKun Wallpaper 代码审计实战分析5:https://blog.csdn.net/rpsate/article/details/122504250
漏洞分析1
审计过程
看到低风险漏洞,其中有Cookie Security:Cookie not Sent Over SSL
,这个漏洞意思就是 setcookie
的 secure
参数没有设置为 True
,如果设置为 True
后,cookie就只能通过https
协议传输了,所以此处不用修改。
Cookie Security:persistent Cookie
,这代表cookie可能存放敏感数据,通过分析得知cookie中没有存放敏感数据。
Cross-Site Request Forgery
,这是指的CSRF漏洞
,我们首先分析一下添加管理员账号处有没有csrf漏洞
。
看到 core/core.php
的19行,此处只对账号和密码长度做了验证,并没有token验证,也没有发现其他防止csrf漏洞
的验证过程。所以此处极大可能存在csrf漏洞
。
漏洞复现
模仿 admin/addAdmin.php
写一个表单,只保留关键代码并添加js代码让表单自动提交。如下图中账号为 rpsate
,密码为 aaaaaa
。将其保存为html文件。
<form id="form" action="http://127.0.0.1/admin/doAdminAction.php?action=addAdmin" method="post">
<input type="text" name="username" value="rpsate">
<input type="password" name="password" value="aaaaaa">
</form>
<script>
var form = document.getElementById('form');
form.submit();
</script>
在登录网站后,用同一浏览器打开这个页面。打开这个页面后就会自动添加一个账号,如下图所示表示添加账号成功。
在实际环境中,黑客会将这个页面隐藏在iframe中,在用户不知不觉中添加账号。
修复方法
修复csrf漏洞
的方法有添加token、验证码、Referer和Orgin字段等等,我们这里的修复方法使用验证token。因为该站不可以ajax跨站请求,那么在没有xss漏洞的情况下是无法通过js获取页面上token的。
将下列代码添加到 admin/addAdmin.php
的顶部位置:
$token = uniqid(md5(time() * mt_rand()));
setcookie('token', $token, time()+60, null, null, null, true);
将下列隐藏表单代码添加在 admin/addAdmin.php
的表单中:
<input type="hidden" name="token" value="<?php echo $token;?>">
要注意
setcookie
的第7个参数一定要设置为true
,不然攻击者可以通过js获取该cookie。
然后再 core/core.php
第20左右添加验证token的代码。注意首先要判断token的长度,然后再判断用户提交的token是否与cookie中token相等。
if (strlen($_COOKIE['token']) != 45 || $_COOKIE['token'] != $_POST['token']) {
alert('token无效!', 'login.html');
}
注意:
alert
是自定义的php函数。
再次测试csrf漏洞,此时已经无法利用该漏洞了。
漏洞分析2
审计过程
注意下面框选的几条数据流,此处没有修改数据库中的任何内容,只进行了查询操作,所以此处不会存在csrf漏洞。
通过审计发现网站中还存在csrf漏洞,但是fortify没有检测出来,这需要审计人员对代码仔细观察才能发现。如下图所示,在 admin/listAdmin.php
中,有一个js函数 deleteAdmin
。该函数向 admin/doAdminAction.php
发送了一个GET请求,表示删除指定id的用户,但是没有携带token。攻击者可以利用该漏洞删除任意用户。
修复方案
修复方法与前面所讲方法相似,只是这次token使用GET传输。在 admin/listAdmin.php
的顶部加上如下代码:
$token = uniqid(md5(time() * mt_rand()));
setcookie('token', $token, time()+60, null, null, null, true);
然后把admin/listAdmin.php
中的 deleteAdmin
函数改成如下所示,其实就是在url后添加了token参数。
function deleteAdmin(id,name) {
if (confirm("你确定要删除"+name+"吗?") == true) {
window.location.href="doAdminAction.php?action=delete&id="+id+"&token=<?php echo $token;?>";
}
}
然后在 core/core.php
的 deleteAdmin
函数中添加如下代码:
if (strlen($_COOKIE['token']) != 45 || $_COOKIE['token'] != $_GET['token']) {
alert('token无效!', 'login.html');
}
还有删除图片功能也存在csrf漏洞,修复方法与此处相同。
漏洞分析3
代码审计
Hidden Field
指的是用了隐藏域,但是该程序在隐藏域中没有敏感信息,所以此处不用处理。
Weak Cryptographic Hash
指的是用了弱hash加密,也就是用了md5加密算法。md5加密算法容易被暴力破解,所以不建议采用md5来加密密码。
看到 admin/doLogin.php
的第10行,此处直接对 $_POST['password']
进行md5运算。假如 $_POST['password']
是一个数组,那么 md5
函数将会出错,那么 $get_password
就等于空。假如 $get_username
的值为一个不存在的用户,那么从数据库中获取到的 $password
也将为空,所以27行的 $password == $get_password
也就等于true
。
payload如下:
username=rpsate&password[]=rpsate&captcha=1412
数据库中必须不存在rpsate账号,验证码要填写准确。
漏洞复现
用burpsuite截取网站登录数据包,如下图所示:
将POST数据中的 password
改成password[]
,然后发送数据包,如下图所示:
修复方案
判断 $_POST['password']
是否为数组,如果为数组则将空值转化为md5后赋值给 $get_password
,同时判断 $password
的长度是否等于32位,如果等于32则说明数据库中有这个用户名,才能让其登录。
if(is_array($_POST['password'])) {
$get_password = md5('');
}else {
$get_password = md5($_POST['password']);
}
if (strtolower($captcha) == strtolower($get_captcha)) {}
修复后再次尝试利用该漏洞:
结语
AKun Wallpaper代码审计实战分析系列到此就结束了!在整个项目的审计过程中fortify帮我们找到了绝大部分漏洞,其中也包括了部分误报,但是通过我们的分析可以很快的判断漏洞是否真实存在,同时我们也通过经验发现了少量漏洞。虽然审计完成并修复了漏洞,但是这并不意味着这套系统就没有漏洞了。我们不可能将漏洞全部修复,只能尽可能的修复更多的漏洞。所以我们还需努力,不断提升自身代码审计能力,使自己在下次审计代码时能够发现更多的漏洞,与君共勉。