这篇文章源于之前做的某银行的红队评估项目,第一次打进去用了一个客服系统的0day漏洞,而且一直打到了银行的核心区。半年后项目续签,开始了第2轮红队评估项目,再想打进去就非常困难了。代码审计出2个SSRF漏洞,但是只能发GET型的HTTP请求,后续通过一系列努力,组合其它漏洞,将这个价值看起来不大的SSRF漏洞,变成了一个危害极其严重的高危漏洞,得到了客户的认可。接下来描述一下具体的漏洞利用过程:
通过网盘搜索找到了一个系统的源代码,但是最后发现这个代码与生产系统部署的代码版本不一样,是一个比较老的代码。经过一天的Java代码审计,只有2个SSRF漏洞被验证在生产系统上是真实存在的。
首先对SSRF漏洞做一个简单介绍:
SSRF漏洞,中文名叫做"服务端请求伪造漏洞"。简单来说,就是攻击者可以在未获取任何外网系统权限的情况下,借助SSRF漏洞,对内网的Web应用、Struts2、Thinkphp、Redis数据库、Zabbix、端口开放情况等等进行探测和攻击。很多Web应用都提供了从其他的服务器上获取数据的功能,根据用户指定的URL,Web应用可以获取图片、下载文件、读取文件内容等。这种功能如果被恶意使用,将导致存在缺陷的Web应用被作为代理通道去攻击本地或远程服务器。
其中,有一个SSRF漏洞,可以直接回显当前页面,而且输出的是字节流,另一个SSRF漏洞只能做探测,没法回显。具体代码审计过程如下:
下图代码的大致意思是:访问当前URL路径时,用户提交的数据会通过doPost方法处理,然后经过this.getUrlStream方法处理。
跟进getUrlStream方法,clientUrl参数允许用户传入一个URL地址(见33行代码),后续代码会对这个URL地址发起GET请求(见39行代码),读取该URL返回数据包,以字节集数据方式返回到当前页面中。
使用burpsuite构造如下数据包,可以直接返回内网相应地址的页面内容(为了防止泄露真实项目信息,截图全部用虚拟机截图替代)。如下图所示:访问外网URL地址http://www.test.com:8080,传入内网URL地址http://10.1.2.1:7001/,可以直接回显该内网地址的网页内容。
这个SSRF漏洞,目前仅能查看内网页面内容,对于一个红队评估项目,客户多半是不认可的,因为不能直观感受到漏洞的危害性。也就是说,到目前为止,这个漏洞的危害仅仅是理论上的。
接下来需要对SSRF漏洞的危害进行验证,这下可让我大伤脑筋,因为这个SSRF漏洞受限非常大,原因如下:
1、代码中限制了URL只能接http型的URL,不支持https;
2、代码中限制了只能发GET请求。
所以流行的SSRF+redis这种依靠其它协议打内网并反弹shell的思路、gopher协议拿权限思路等等,在本次测试中不适用,因为不支持相关协议。
那如何证明这个受限的SSRF漏洞的危害性呢?我想到了以下思路:批量慢速扫描内网的80、8080、8888等常见Web端口(443端口直接放弃,因为不支持https),然后对扫描出的内网Web应用系统进行漏洞测试,由于仅支持GET请求,漏洞类型及漏洞利用条件限制为,一个URL访问就能直接拿权限的漏洞:
为了避免大批量扫描,需要确定内网有哪些ip段。于是我收集整理了旗下所有子域名、外网IP段的敏感信息泄露问题,汇总成一个内网ip地址列表,接着整理成一个内网ip段列表(通过这个案例也可以了解到,“泄露内网IP地址”这种简单的漏洞,也是需要修复的),效果如下:
内网泄露ip地址 | 整理成内网IP段 |
---|---|
10.2.1.23 | 10.2.1.1/24 |
192.168.10.121 | 192.168.10.1/24 |
10.0.12.121 | 10.0.12.1/24 |
10.0.253.10 | 10.0.253.1/24 |
10.10.1.34 | 10.10.1.1/24 |
接下来对这些内网ip地址段进行单线程的批量扫描,线程太高容易引起内网的流量监控的报警。
结果没有我想象中的那么容易,我一直在内网慢速扫了三、四天,期间一直守在电脑前,以免出现异常的时候,及时联系客户进行排查。最后终于找到了一个内网的taskman系统,这个系统在之前金融内网见过,存在未授权访问漏洞,可以控制很多生产业务的关停,至此,一个只能发HTTP的GET请求的SSRF漏洞,就变成了一个严重的高危漏洞,而且可以对内网生产系统造成严重威胁。
如下图所示,结合外网的SSRF漏洞,攻击队员是可以直接暂停内网生产系统的业务运行,这个漏洞如果被攻击者利用,那危害是非常大的。
为了方便自己的内网渗透,同时也为了给客户展示漏洞的危害性,我编写了一个SSRF代理工具(其实就是一个简单的HTTP代理工具),用java Swing做了一个图形界面,点击“浏览”按钮,可以利用此SSRF漏洞直接访问到内网应用系统。
细心的读者可能会有疑问,对于这里的“暂停”、“执行”功能,想要触发这种按钮事件,一般都是需要发送POST请求的,这个SSRF漏洞情况下不能用。但是结果是非常幸运的,因为它既支持“POST”请求、也支持“GET”请求。因为程序员有个习惯,喜欢这样写代码:“GET”请求处理默认交给“POST”请求去处理。