前言
▶ 通过前面5期的代码审计,我们已经修复了这套系统的绝大部分漏洞,同时也学习到了不少知识。这一篇文章是这一个系列的最后一篇文章。
漏洞分析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帮我们找到了绝大部分漏洞,其中也包括了部分误报,但是通过我们的分析可以很快的判断漏洞是否真实存在,同时我们也通过经验发现了少量漏洞。虽然审计完成并修复了漏洞,但是这并不意味着这套系统就没有漏洞了。我们不可能将漏洞全部修复,只能尽可能修复更多的漏洞。所以我们还需努力,不断提升自身代码审计能力,使自己在下次审计代码时能够发现更多的漏洞,与君共勉。
来源 | 刘正波
西柚网安
扫描二维码并关注
网安知识一网打尽
原文始发于微信公众号(西柚网安):AKun Wallpaper 代码审计——实战分析(六)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论