spring-messaging Remote Code Execution 分析-【CVE-2018-1270】
漏洞公告
https://pivotal.io/security/cve-2018-1270
漏洞影响版本:
- Spring Framework 5.0 to 5.0.4
- Spring Framework 4.3 to 4.3.14
- Older unsupported versions are also affected
环境搭建
利用官方示例 https://github.com/spring-guides/gs-messaging-stomp-websocket ,git clone后checkout到未更新版本:
用IDEA打开gs-messaging-stomp-websocket目录下的complete项目,修改app.js中的第15行:
增加了一个header头部,其中指定了selector
,其值即payload。
漏洞利用
点击connect后建立起连接,在文本框中随意输入,点击Send,触发poc:
漏洞分析
当在 http://localhost:8080/ 中点击Connect后,在app.js中,有如下代码,会建立起Websocket连接:
其中header
中指定了selector
,根据 Stomp Protocol Specification, Version 1.0,通过指定对应的selecttor,可以对订阅的信息进行过滤:
在 org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java 第140行,对这个header参数进行了接受和处理:
如图所示,此次连接对应的sessionId为mrzfa005
,subsId为sub-0
。
之后,在 http://localhost:8080/ 中输入任意字符串,点击send。spring进行了一系列处理后,开始向消息的订阅者分发消息,在 org/springframework/messaging/simp/broker/SimpleBrokerMessageHandler.java:349 行:
其中message保存了此次连接/会话的相关信息:
跟入 this.subscriptionRegistry.findSubscriptions
至 org/springframework/messaging/simp/broker/AbstractSubscriptionRegistry.java:111 行:
message作为参数被传入 findSubscriptionsInternal
,在return处继续跟进至 org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java:184行
其中result变量值如下:
该变量即 org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java:201行的filterSubscriptions方法的allMatches
变量,跟进至两层for循环
通过两次getSubscriptions
操作,此时取出了先前的配置信息,sub变量值如下:
接下去第 207 行将selector表达式取出:
第217行:
通过调用了expression.getValue(context, Boolean.class)
,触发payload,执行了spel表达式,远程命令执行成功。