spring-messaging 远程代码执行漏洞分析
字数 1763 2025-08-03 10:57:11
Spring Messaging 远程代码执行漏洞分析教学文档
漏洞概述
Spring Messaging 组件中存在一个远程代码执行漏洞,攻击者可以通过构造恶意的 STOMP 消息触发 SpEL 表达式注入,从而在目标服务器上执行任意代码。
环境搭建
-
获取漏洞环境代码:
https://github.com/spring-guides/gs-messaging-stomp-websocket/tree/6958af0b02bf05282673826b73cd7a85e84c12d3 -
使用 IntelliJ IDEA 导入项目:
- 打开
pom.xml文件 - 配置运行环境:
- 点击 "Edit Configurations"
- 添加 Maven 配置
- 在 "Command line" 输入:
spring-boot:run
- 打开
漏洞复现步骤
- 访问应用:
http://127.0.0.1:8080/ - 点击 "Connect" 按钮建立 WebSocket 连接
- 使用抓包工具拦截 WebSocket 通信
- 当出现 "WebSockets message to" 消息时,修改内容为:
["SUBSCRIBE\nid:sub-0\ndestination:/topic/greetings\nselector:new java.lang.ProcessBuilder('calc.exe').start() \n\n\u0000"] - 返回页面,输入任意内容并点击 "Send"
- 观察计算器程序被弹出(证明代码执行成功)
漏洞原理分析
WebSocket 与 STOMP 协议
- WebSocket 是 HTML5 提出的实时通信协议
- STOMP (Simple Text Oriented Messaging Protocol) 是 WebSocket 的子协议,定义了消息传输格式
- 常用 STOMP 命令:
- CONNECT/CONNECTED
- SEND
- SUBSCRIBE/UNSUBSCRIBE
- BEGIN/COMMIT/ABORT
- ACK/NACK
- DISCONNECT
漏洞触发流程
-
订阅阶段 (SUBSCRIBE):
- 攻击者发送恶意 SUBSCRIBE 消息,其中包含
selector头部 - 服务端调用
DefaultSubscriptionRegistry.addSubscriptionInternal方法 - 方法中通过
SimpMessageHeaderAccessor.getFirstNativeHeader获取selector值 - 使用
SpelExpressionParser.parseExpression解析 selector 值(恶意 SpEL 表达式)
- 攻击者发送恶意 SUBSCRIBE 消息,其中包含
-
存储阶段:
- 解析后的表达式被存储在
DefaultSubscriptionRegistry中 - 与 sessionId 和 subscriptionId 关联
- 解析后的表达式被存储在
-
触发阶段 (SEND):
- 当发送 SEND 消息时,调用
AbstractSubscriptionRegistry.filterSubscriptions - 方法遍历所有订阅,获取存储的表达式
- 调用
expression.getValue执行 SpEL 表达式 - 恶意代码被执行
- 当发送 SEND 消息时,调用
关键代码分析
-
表达式解析:
String selector = SimpMessageHeaderAccessor.getFirstNativeHeader( this.getSelectorHeaderName(), headers); if (selector != null) { expression = this.expressionParser.parseExpression(selector); } -
表达式存储:
this.subscriptionRegistry.addSubscription(sessionId, subsId, destination, expression); -
表达式执行:
if (Boolean.TRUE.equals(expression.getValue(context, Boolean.class))) { result.add(sessionId, subId); }
补丁分析
补丁链接:
https://github.com/spring-projects/spring-framework/commit/e0de9126ed8cf25cf141d3e66420da94e350708a#diff-ca84ec52e20ebb2a3732c6c15f37d37aL217
主要修改:
- 将
StandardEvaluationContext替换为SimpleEvaluationContext SimpleEvaluationContext限制:- 不支持 Java 类型引用
- 不支持构造函数调用
- 不支持 bean 引用
防御建议
- 升级 Spring Framework 到已修复版本
- 如果无法立即升级,可考虑:
- 禁用 STOMP 的 selector 功能
- 实现自定义的
SubscriptionRegistry过滤恶意表达式
- 对 WebSocket 端点实施身份验证和授权
扩展知识
-
SpEL 表达式注入:
- Spring Expression Language (SpEL) 是 Spring 的表达式语言
- 类似其他模板注入漏洞,当用户输入被直接解析时可能导致 RCE
-
WebSocket 安全:
- 确保所有 WebSocket 端点都有适当的访问控制
- 考虑对消息内容进行验证和过滤
-
STOMP 协议安全:
- 限制可用的 STOMP 命令
- 对订阅目标实施白名单控制
总结
该漏洞展示了即使在使用现代协议如 WebSocket 和 STOMP 时,如果不对用户输入进行严格验证,仍然可能导致严重的安全问题。开发者应当对所有用户提供的数据保持警惕,特别是在涉及表达式解析或代码执行的场景中。