CVE-2018-1270&CVE-2018-1275 spring-messaging远程代码执行漏洞分析

漏洞描述

Spring框架版本5.0-5.0.4,4.3-4.3.15存在CVE-2018-1270和CVE-2018-1275漏洞可导致远程代码执行。在引入且使用spring-messaging组件时,攻击者可通过WebSocket向服务器端发送携带有恶意代码的STOMP消息,从而导致远程代码执行攻击。

注意由于可能官方版本发布流程或代码管理上所犯低级错误,导致4.3.14-4.3.15版本升级中该漏洞所涉及文件并未更新,所以CVE-2018-1270在4.3.14版本中并未修复,就有了最新的CVE-2018-1275漏洞,并在4.3.16版本中得到了修复。

机制分析

STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议,用于服务器在客户端之间进行异步消息传递。STOMP帧由命令,一个或多个头信息、一个空行及负载(文本或字节)所组成

其中可用的COMMAND包括:

CONNECT、SEND、SUBSCRIBE、UNSUBSCRIBE、BEGIN、COMMIT、ABORT、ACK、NACK、DISCONNECT

客户端可以使用SEND命令来发送消息以及描述消息的内容,用SUBSCRIBE命令来订阅消息以及由谁来接收消息。这样就可以建立一个发布订阅系统,消息可以从客户端发送到服务器进行操作,服务器也可以推送消息到客户端。

通讯过程:

1、客户端与服务器进行HTTP握手连接

2、客户端通过发送CONNECT帧建立连接

3、服务器端接收到连接尝试返回CONNECTED帧

4、客户端通过SUBSCRIBE向服务端订阅消息主题

5、客户端通过SEND向服务端发送消息

要从浏览器连接,对于SockJS,可以使用sockjs-client。对于STOMP来说,许多应用程序都使用了jmesnil/stomp-websocket库(也称为STOMP.js),它是功能完备的,已经在生产中使用了多年,但不再被维护。目前,jsteunou/webstom-client是该库最积极维护和发展的继承者。

示例代码:

connect接受一个可选的headers参数用来标识附加的头部,默认情况下,如果没有在headers额外添加,这个库会默认构建一个独一无二的ID。用户定义的headers通常用于允许使用者在进行订阅帧中的selector来过滤基于应用程序定义的headers消息。

补丁分析

分析补丁情况,主要涉及文件DefaultSubscriptionRegistry.java

这里发现主要修改文件为DefaultSubscriptionRegistry,去掉了StandardEvaluationContext,改用SimpleEvaluationContext,继续查看补丁信息

可以看到补丁对比代码中使用了expression.getValue()方法,熟悉spel表达式注入的同学知道这里很可能会有问题,并且context来自于引用StandardEvaluationContext处理过的message,那接下来的分析就重点关注这里了我们找到。

漏洞触发分析

我们先找到expression.getValue()处下断点,查看调用栈,用到了sendMessageToSubscribers函数,也就是说客户端在发送send message时会调用getValue。

在sendMessageToSubscribers处下断点详细跟踪,发现后端通过客户端的订阅ID subId来确认具体会话,并从会话headers中获取selector值当作expression最后执行,我们说expression.getValue()存在表达式执行的风险,那么这里的headers在之前的STOMP机制介绍中有提到过,headers可以在客户端进行定义,也就是说只要我们在headers当中的selector传入poc就可以达到表达式注入的目的。

而headers根据我们之前的介绍,它会在CONNECT阶段就定义好了,也就是说这个漏洞需要两步触发:

  1. 在客户端定义headers并且其中包含selector,这里传入spel,服务端和客户端建立起连接后,服务端接收到SUBSCRIBE订阅消息并获取headers
  2. 客户端发送消息,服务端在当前会话中查找headers中的selector值最终执行

接下来我们根据之前的分析传入poc,并分析建立CONNECT的过程中时候获取headers中selector的整个过程

注册订阅消息,并从客户端获取headers和selector进行绑定

接下来send message的流程和之前一样,通过subId获取到会话headers中的selector,调用filterSubscription对消息进行过滤,最终到通过expression.getValue()执行了POC

处理建议

5.0.x版本用户升级至5.0.5

4.3.x版本用户升级至4.3.16

参考链接

https://pivotal.io/security/cve-2018-1270

https://pivotal.io/security/cve-2018-1275

https://stomp.github.io/stomp-specification-1.2.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python3

python3--threading模块(线程)

程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态...

50920
来自专栏魏艾斯博客www.vpsss.net

AppNode-Linux 服务器集群管理面板安装教程

36820
来自专栏云计算与大数据

研发:Idea工具因为版本工具设置问题,导致全是红色

I have the current status of my files in the folders coloured red/brown. I tried...

14830
来自专栏用户画像

3.1.1内存管理的概念

内存管理是操作系统设计中最重要和最复杂的内容之一,虽然 计算机硬件一直在飞速发展,内存 容量也在 不断增长,但是仍然不可能将用户进程所需要的全部程序和数据放入主...

8310
来自专栏Golang语言社区

Gogland更名为GoLand,并附加新功能

IDE改名 Jetbrains在2017年11月02日正式对外公布,Gogland IDE正式改名为GoLand。在社区之前的文章《你们使用的Go IDE要改名...

46590
来自专栏运维咖啡吧

Django配置Celery执行异步任务和定时任务

celery是一个基于python开发的简单、灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的机器/进程/线程上执行任务调度。采用典型的生产者-...

26820
来自专栏PHP实战技术

浏览器访问一个网站所经历的步骤

  搜索操作系统自身的DNS缓存(浏览器没有找到缓存或缓存已经失效)

26580
来自专栏散尽浮华

如何查询一个进程下面的线程数(进程和线程区别)

在平时工作中,经常会听到应用程序的进程和线程的概念,那么它们两个之间究竟有什么关系或不同呢? 一、对比进程和线程 1)两者概念 . 进程是具有一定独立功能的程序...

32890
来自专栏张善友的专栏

Windows安装和使用zookeeper

之前整理过一篇文章《zookeeper 分布式锁服务》,本文介绍的 Zookeeper 是以 3.4.5 这个稳定版本为基础,最新的版本可以通过官网 http:...

26290
来自专栏小樱的经验随笔

【干货分享】dos命令大全

一般来说dos命令都是在dos程序中进行的,如果电脑中安装有dos程序可以从开机选项中选择进入,在windows 系统中我们还可以从开始运行中输入cmd命令进入...

33690

扫码关注云+社区

领取腾讯云代金券