01
前情提要
在一个风和日丽的上午,接到了一个产品的测试任务,这个产品提供了一个WEB后台,由于产品的部署需要大量的依赖和环境,所以产品线提供的是一份已经部署好该产品服务端的虚拟机镜像,这也为我在测试本文中遇到的问题过程中起到了很多帮助。
02
心路历程
系统在本地虚拟机里部署好之后进行了初步的测试,发现了一些常见的WEB漏洞。
话说小组里大佬太多,平时搞windows客户端方面的测试干不过他们,好不容易来了个web,我计划趁大佬们还没动手,直接把能发现的漏洞全给梭哈了。
邪恶的我直接将镜像里面的服务端代码打包,使用jd-gui反编译然后导出成源码压缩包,放到部门的checkmarx上扫一扫。
白盒扫的过程中自己在审计它的代码。
03
发现任意文件上传漏洞
首先是在本地审计代码的时候发现了个隐藏的文件上传接口,存在任意文件上传漏洞。
由于中间件权限较高,并且服务端没有恶意字符过滤,在执行任意文件上传时可以使用../方式跨目录上传,如下图使用../在发送请求将文件上传到根目录。
此处在linux系统上就已经可以通过覆盖计划任务的方式实现命令执行,但是直到我经历了后面的事,这个任意文件上传才刚刚开始。
04
Process_Control
测试了一会之后去看看源代码扫描这边的结果,看到了个被标记为中危的漏洞Process_Control。
Process_Control这是什么东东?看了一下源码,哦,原来是加载了个外部的库。
参考freebuf上的文章:《缺陷周话:进程控制》(https://www.freebuf.com/articles/web/209789.html)
进程控制的危害:在使用动态库加载函数时,如果攻击者可以把一个同名的恶意库文件放置在搜索顺序靠前的位置,甚至优先于应用程序所需加载文件的位置,那么应用程序将会加载该恶意库的副本,而不是原本所需的文件,从而导致恶意代码执行。
自己本地写了个demo测试一下System.loadLibrary。
在java中的System.loadLibrary会动态的加载库文件,如果是linux系统则加载.so,在windows系统上默认加载.dll。
如果你的代码如上图所示,在linux中最终加载的so文件名为libdemo_java.so,加载过程也有优先级顺序。
这时我联想到上面的任意文件上传,如果将这个库覆盖为恶意的so文件,那不就可以实现命令执行了,秉承着知行合一的原则,有想法了咱就尝试一下,直接开干。
05
你能不能别改我文件啊
直接在虚拟机里搜一下库在哪。
有了路径我们去使用msfvenom生成一个反弹shell的so文件。
文件生成后,我们使用hash工具计算一下我们生成的so文件的hash值。(此处要考)
我们在服务器上查看一下原so文件的hash值。
接着我们使用burpsuite-> Repeater工具修改请求,修改filename使用../覆盖服务器上的目标so文件。
删除原上传请求中的文件内容,在内容部分右键Paste from file,选择我们的恶意so文件。
点击send->上传成功->朴实无华
看一下传上去的文件的hash,?????????大哥,您哪位啊,既不是我们生成的so,也不是原so。
此时我第一个想法是,难道是Content-Type类型有问题,我选择了错误的类型导致文件内容被不知名力量篡改了。
在网上找到.so文件使用的Content-Type是 “application/ octet-stream”,发送后依然是sha256为“be1”开头的这兄弟。
当时在各种各样的尝试过程中内心逐渐走向疯狂,burpsuite作为我可靠的伙伴,我竟然开始质疑它,遂拿出winhex逐个byte比对,左侧为该文件在请求体中的情况,右侧为使用winhex打开的情况。
对比发现Repeater中的文件内容比原文件多了好多,我一位一位比对了一下,从中间开始隔几位就会有一个被插进来的byte,最后更是多了一大段不知道哪里的数据。。。。眼睛差点瞎了。
随后将服务端的so文件、burpsuite传输的流、以及winhex打开的源文件进行比对:
发现burpsuite对so文件进行了处理,并且将处理后的文件原封不动的传输到服务器上,发现了与源文件对比已经变化的情况。
06
用python解决
无力研究为什么burpsuite加载我的so文件时会在请求中修改文件内容了,最终自己编辑了个脚本实现了正常的上传。
07
反弹shell
将服务端重启,程序代码自动加载我们的恶意库文件,shell反弹成功。
08
修复建议
1.中间件使用普通用户运行降低权限
2.服务端白名单过滤后缀
3.文件名随机化生成
4.../等特殊字符的检查过滤
5.库文件加载前的检查
09
总结
1.最后能利用成功还是依赖了任意文件上传漏洞的强大能力。
2.利用后需要重启服务才能让恶意库文件被加载,理想场景可能需要使用ddos等方式迫使他重启,不知道还有其他思路没有。
3.so文件由于没有实现原库函数的业务功能,导致服务器重启后部分功能无法使用,在真实环境中还需要将调用过程转到真实的so那边去。
4.哎,这篇文章用来纪念我在burpsuite上对着二进制和winhex上的二进制一个一个字符比对的痛苦经历,感谢msfvenom的马不算太大,没累瞎我。
5.burpsuite,你失去了我的信任。
本公众号所发布的文章及工具代码等仅限交流学习,本公众号不承担任何责任!如有侵权,请告知我们立即删除。