..

模拟众测漏洞 writeup

write-up

已经告诉 flag 位置,那么朝着这么目标渗透吧。

一开始是一个后台登录界面,想要模拟的环境是后台对外开放并且可被注册,在众测中也经常遇到这类漏洞,比如员工系统或者协同办公系统,注册登录后在内部的 wiki 中发现一些敏感信息。 登录处有预留一个SQL注入,想考的是任意账号登录,所以在代码中限制了长度,SQLMAP 默认没有尝试or注入,好像跑不出来,这个位置的注入还算隐秘,主要看渗透者细不细心,如果不细心怎么办?没关系呀~ 拿出打 CTF 的套路,页面中的一切都有可能是tips,就好像玩密室逃脱,慢慢找线索。 //唉,别打我

一般隐藏提示的地方常见于 html 或者 http header 中,很少有人注意到图片吧,诶厉害了,顺便还能涉及到隐写术,越来越像 CTF 了啊喂。 很明显这不是一张普通的萌妹子图片,binwalk 告诉我们这张图片经过 ps 处理之后又捆绑了一个charles201610201126.zip文件, 压缩包中是 charles 的保存文件,修改后缀为har然后用 charles 打开, 当然这里想考的是注册 admin 的姿势,代码是这样写的

if (strlen($user) > 5) {
    echo "<p>waring:注意帐号长度不超过5位</p>";
} elseif ($user == 'admin') {
    exit('<script>alert("admin已被注册")</script>');
}

之前在微博放出的 tips 有提到这点,代码和数据库差异性导致的问题,这类问题虽然比较少见,记得最早好像在道哥的《白帽子讲 Web 安全》中看到过,user 字段长度设定为5,但没有在代码中对传入的 user 值进行长度限制,以至于可以注册一个用户名为admin1的账号,写入数据库时由于长度限制会自动截断丢弃,这样实际上还是注册了admin

然后接下来注册流程会向邮箱发送激活账号链接,需要 user 和 token 值对应才行,这里模拟的是众测中很常见的密码找回案例, token看似是一组没有规律的字符串,其实是伪随机,有经验的同学可能会尝试破解这串 md5 观察是基于什么加密的。 很明显是time()函数的一次 md5,很容易就能预测任何时间的token 值,这里有个小知识,观察 POST 的时间一般向后几秒就是正确的 token,但要注意,time()函数获取的时间戳是会和本地时间相差八小时,因为从php5.1.0开始,php.ini里加入了date.timezone这个选项,默认情况下是关闭的,也就是显示的时间(无论用什么php命令)都是格林威治标准时间 和我们的时间(北京时间)差了正好8个小时。

进入到 admin 管理员账号,看到只有一个上传图片的功能(懒,没有写其他功能),看到有上传,大家惯性思维都会先测有没有任意文件上传的漏洞,不过仔细看上传的文件会被重命名,这里代码是这样写的,这样除非有解析漏洞或者文件包含。这里也是最坑的地方,很多同学到这里就没了思路。

function upload(){
    $file = $_FILES['file'];
    # 没文件上传就退出
    if (!isset($file['name'])) {
        exit;
    } elseif (!(substr($file['name'], -3, 3) == 'jpg')) {
        exit('<script>alert("仅支持jpg")</script>');
    }
    # 文件名不可预测性
    $salt = '8gs@22m.sa(fsf6n"7s';
    $name = md5(md5($file['name'] . $salt) . $salt);
    # 判断是否是通过HTTP POST上传的
    if (!is_uploaded_file($file['tmp_name'])) {
        return;
    }
    # 上传文件的存放路径
    $upload_path = "./img/";
    # 移动文件到相应的文件夹
    if (move_uploaded_file($file['tmp_name'], $upload_path . $name)) {
        echo "<img src='./img/$name'>";
        echo "<a href='del.php?del={$name}'>删除此图片</a>";
        echo $name;
    } else {
        exit("Failed!");
    }
}

这里想模拟的是发生在众测中的一次真实的"事故",某位白帽子意外删除了整个图片文件夹,不过并不是白帽子的锅,真的是开发太蠢,猜测可能是这样写的。

function del($img_name){
    shell_exec(rm -rf . $img_name);
}

大概 url 是这样的 xxx.com/userid/username/img/2016/01/01/imgname.jpg 白帽子测试把imgname.jpg去掉,可能是想看是否有文件遍历等问题,然后就 gg 了。不过最后协助厂商通过技术手段还是把文件找回来了。

这么经典的"事件",必须要拿出来分享一下。我这里没有敢用rm -rf 只把环境模拟出来,因为是linux 的命令注入,命令注入太危险,也从代码中过滤了很多可以用来 Bypass 的关键字符,留出来 ; 用作拼接,同时做了命令白名单和长度,这就很蛋疼,不过会echo出经过过滤后的字符。 那么我们知道 flag 是在当前用户目录下,直接去读取肯定是不行的了,因为这里不能回显而且还会把 . * / 这样的字符过滤掉,那要怎样才能获取到这个 flag 文件呢?可以用 tar 打包当前用户目录下的文件可以用 ~ 然后会给出提交 flag 的地址 不过直接访问的话会403 这里想要模拟的是众测中遇到的一次绕云 Waf 的实例,主机开放了** http proxy **其实之前乌云主站也有过这样的漏洞案例,对外开放的代理带来的一系列安全问题,开启了通向内网的隧道,如果是 Socks 代理可玩的就更多了。 设置代理,访问 http://127.0.0.1/flag/flag.php