前言

一个平平无奇的周末,哥们儿发来消息,说自己手上有个产品安全测试搞不定,想让我帮帮忙——本来是不乐意的,但海底捞实在是香,所以有了这次受委托的产品安全测试。

一、组件漏洞排查

在测试前,开发已将【产品用到的组件】以发了过来。而咱们要做的,就是确认这些组件是否存在已披露的漏洞。

在这部分工作中,会经常用到几个平台,因此也就介绍给各位师傅。


一般情况下,此环节主要靠个人经验完成,但由于开发不一定一次把组件和版本给你说全了,因此常常需要测试到后期,比如拿到个shell,才能摸清整个的组件情况。那么,开始吧。
本次测试的组件如下:

  • ThinkPHP 3

    TP 3:但没说清楚是哪个子版本,tp<=3.2.3是存在注入漏洞的。一般可以通过路由报错来确定版本,或者在有源码时直接查看配置文件(可全局搜索THINK_VERSION)。

  • PHP 5.4

    PHP 5.4:版本不高。据我所知,首先是不存在%00截断问题(在PHP 5.3.24修复),还有其它问题吗,暂时没想到——不着急,咱们继续往后走。

二、全端口扫描

WEB产品,肯定是部署在某台主机环境上的,因此主机漏洞也需要关注,否则上线时容易被黑阔撸穿。
全端口扫描,本来是直接命令行运行nmap -p-直接冲即可。
不过,这一回,我还想介绍一种全端口扫描的技巧,利用环境变量, 先快速扫全端口,再有针对性地对开放端口做漏洞扫描,命令如下:

ports=$(nmap -p- --min-rate=1000 -T4 10.13.38.11 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -sC -sV 10.13.38.11

扫描结果: 略

三、WEB目录爆破

爆破web目录的原因呢,其实跟渗透一样:开发常常会遗漏一些未授权访问的api或备份文件,越先于攻击者找到它们,产品的风险就越低。例如Spring BootActuator未授权,就是由于/actuator/env接口未授权访问所导致的。
![图片.png](https://cdn.nlark.com/yuque/0/2020/png/166008/1604386882246-cddca7ca-8e59-4a71-9693-fe384b1a092a.png#align=left&display=inline&height=522&margin=%5Bobject%20Object%5D&name=%E5%9B%BE%E7%89%87.png&originHeight=522&originWidth=938&size=90267&status=done&style=none&width=938)
工具方面,我选用的目录爆破工具是 dirsearch + Dirbuster , 这俩都支持保存扫描结果,但我对它俩的看法是这样的:

  • dirsearch:重在快速确定重要的路径以确定问题,如actuator未授权、备份文件、api接口、常见后台等;
  • Dirbuster:重在全面地爆破路径。使用40万关键词级别的medium字典,可以爆破出不少文件夹,效果还不错。

扫描结果: 略

四、WEB安全内容测试

经过紧张的测试,共发现以下几处漏洞,下面一起来看看。

0x01 服务端自动填充密码

既然是产品安全测试,那开发必然是要给账号、密码的,但成功登录后,我猛然意识到不对劲。
我在另外一台机器上访问后台,看到登录口赫然填着密码——合着在上一次成功登录后,服务端直接将账号、密码写在前端页面中了。真有你的!
再理一理逻辑:密码既然不是浏览器自动填充的,那必然就是服务端(直接将上一次成功登录的账号密码,作为默认值填充到输入框中了(也许是为了方便),妥妥的逻辑问题。另外,此处无验证码、且无防止重放的token,所以存在账号、密码可被暴力破解的风险。三分钟,两个洞,妥妥的低危小子!

好家伙,测试一整天就找到了明文密码漏洞,真有你的!

0x02 XSS

进到后台,在属性编辑页面习惯性地插入<">,观察后端是否对页面的输出进行了HTML实体转义,结果发现未对尖括号转义。下图的左边部分,可以看到,<已经跟HTML代码"融为一体"了,

那么可以用右尖括号>闭合<span标签,我们填写一个弹框的payload,<"><script>alert(/xss/)</script>,刷新——弹框——没毛病,存储型XSS到手。

既然有了存储型的XSS,反射型的XSS肯定也少不了,简单找了找,又发现了一处接口存在GET类型的反射XSS,主要还是服务器返回的页面类型是Content-Type: text/html, 即浏览器会把页面内容当成html页面进行渲染,另外该接口的特点是输入的参数会体现在响应中,二者结合即为反射XSS。

哪个打工人愿意只止步于XSS呢?我们继续找找有没有更严重一些的漏洞。

0x03 命令注入

复杂命令,简单注入。
看了看后台的功能点, 是偏向于给网管用的运维工具, 比如可以对Linux服务器做登录扫描, 当然, 前提是咱们得输入ssh的账号、密码。

越高端的操作往往越接近底层,越底层的东西往往越危险。

大胆猜测:要完成登录SSH的操作,后端实现可能是调用的sshpass,说不定存在OS命令注入的问题,试试?

# 用sshpass直接远程连接某台主机
sshpass -p password ssh root@127.0.0.1

&&||><一直试到反引号,都是直接报错,好家伙,都给过滤了呗。然而转机常在灰头土脸时到来: 开发忘记了过滤$和括号(),一发$(sleep 5),睡了五秒再醒过来,正好拿到shell。

拿到shell后的第一件事: 拿授权, 拖代码, 审计。

0x04 SQL注入

这套系统, 跟我审计OneThink的那篇文章一样,都是TP3的框架: 一开始想着看看是否也存在前台登录绕过的问题

前台登录绕过:在USERNAME处实施注入, 用UNION SELECT联合查询, 控制数据库返回的密码值, 使其与PASSWORD值相同, 以此来达成前台登录的绕过.

先说结论: 由于系统的用户名参数并无注入,即无法控制数据库返回的密码值,那么就算知道了密码的加密方式,也无法构成前台登录的绕过。意味者后台也没有。后台存在不少用$where变量,都是拼接的用户输入, 用单引号闭合即可实施注入,SQLMAP一把梭即可直捣黄龙。
不过,话又说回来:都有shell了, 要后台的SQL注入干嘛,命令执行不香?

0x05 前台SSRF

在一路审计代码的过程中, 又发现了几处缺乏认证的PHP散文件, 首先找到的是两处SSRF

HTTPS型SSRF

注册的时候,发现请求数据里存在一个ip地址的字段, 跟到源码里, 原来后端会对其进行curl请求

只不过, 由于CURLOPT_FOLLOWLOCATION属性并未启用, 导致不能使用302跳转, 只能做https请求

万金油型SSRF


还有一个支持302的SSRF问题: 跟进go函数, 它是一个开启了CURLOPT_FOLLOWLOCATION的CURL封装, 那么我们就能用302跳转到gopher协议来打内网。当然:此处只做论证,不演示。

0x06 前台任意文件上传

其实,刚刚那张图中的分支case 123处,是存在任意文件上传的, 只不过文件是传到了内网,并无实际用处。
后来,我注意到使用了一个文件上传相关的组件,在xxxxxx/uploadfile/app.php中, 存在以下代码

//app.php
<?php
$DIR = 'base';
$src = file_get_contents('php://input');

if (preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)) {
    $appUrl = sprintf(
        "%s://%s%s",
        isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',
        $_SERVER['HTTP_HOST'],
        $_SERVER['REQUEST_URI']
    );
    $appUrl = str_replace("app.php", "", $appUrl);

    $base64 = $matches[2];
    $type = $matches[1];
    if ($type === 'jpeg') {
        $type = 'jpg';
    }

    $filename = md5($base64).".$type";
    $filePath = $DIR.DIRECTORY_SEPARATOR.$filename;

    if (file_exists($filePath)) {
        die('{"result" : "$appUrl".'base/'."$filename"');
    } else {
        $data = base64_decode($base64);
        file_put_contents($filePath, $data);
        die('{"result" : "$appUrl".'base/'."$filename"');
    }

这真是教科书级的上传漏洞啊, 不但能让人学正则, 又熟悉了伪协议。本来我还准备了HTML的上传表单,没想到连这步都省了。
整个文件的逻辑是:通过正则,提取出形如data:image/XXXXX;base64,YYYYYYY的字符串中XXXXX
YYYYYYY值,分别作为文件后缀和文件内容。
那么利用方式就呼之欲出了:直接将上传内容进行base64编码,把数据放到POST_DATA里,实现无损上传PHP文件。并且,由于文件内容缺少PHP脚本的特征,上传过程顺带把WAF给绕了——我直呼内行

data:image/php;base64,dXBsb2FkIHRlc3Q8P3BocCBwaHBpbmZvKCk7ID8+

前台上传, 一发入魂,直接起飞。
实际上,XSS、SQLi 、SSRF,都只是手段,不是目的——要是存在前台RCE问题的话,为什么不提出来呢?

0x07 前台命令执行

经过复杂的变量跟踪, 最终发现一处获取网管机器版本的接口存在未授权命令执行, 可谓一瞬起飞。

总结

弦歌渐远,海底捞吃完了,生活还得继续:最近在看阿里巴巴的Java开发手册,作者在第一章里就提到了SQL注入,开发牛,安全的知识也不落下,可见功底之深厚。
其实,开发也好,安全也罢,都不能闭门造车:开发需要了解安全,安全也应当学学开发;
毕竟,不懂开发的我,现在还在打工。

点击收藏 | 3 关注 | 2
登录 后跟帖