Spring Cloud Gateway 的 SpEL 表达式注入漏洞
由于我是在公司电脑刚入职所以从头配了个ubuntu流程大致先换apt、dns、dockerhub image缓存服务器镜像源,把docker和dockercompose下好拉取镜像我这里因为拉过了所以重启就直接起来了。前面两个去环境配置里找这里附上最后一个dockerhub直接复制粘贴下面整条命令到终端执行它会自动为你添加几个当前可靠的加速地址并重启 Docker。bashhighlighter- awk# 配置阿里云、中科大、网易三个公共镜像源作为加速器 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json -EOF { registry-mirrors: [ https://docker.mirrors.ustc.edu.cn, https://hub-mirror.c.163.com, https://mirror.ccs.tencentyun.com ] } EOF # 重启Docker服务使配置生效 sudo systemctl daemon-reload sudo systemctl restart docker入门指南 | Vulhub漏洞环境使用vulhubcd到要复现的cve后直接docker compose up -d就能拉取镜像并启动环境了这个用的是8080端口有的人可能bp用的这个端口可能会导致冲突什么的可以改yaml文件也可以直接改自己的bp配置我这里用的yakit没有这个问题Spring Cloud Gateway它统一接收所有外部请求根据规则决定转发到哪个后端服务并在转发前后执行统一的过滤逻辑鉴权、日志、限流等是 Spring Cloud 生态中的API 网关组件SpEL 表达式Spring Expression LanguageSpring 表达式语言Spring自己的嵌入式脚本它能在程序运行期间动态地计算值、调用方法、访问属性。它用来解决什么问题假设你想在配置文件里写这样一个逻辑highlighter- awk// 需求如果用户等级是VIP折扣就是0.8否则是1.0 // 问题配置文件通常只能写死静态值不知道怎么表达这个逻辑不用 SpEL你只能在代码里硬编码或者在配置里写多个参数然后在 Java 代码里写if-else。用 SpEL你可以直接在配置里写表达式让 Spring 在运行时自动计算结果highlighter- coffeescriptdiscount: #{ user.level VIP ? 0.8 : 1.0 }漏洞成因/actuator/gateway/routes/test这是 Spring Boot Actuator 暴露的管理端点用于动态添加路由规则。正常情况下管理员可以通过它来配置网关如何转发请求。/actuator/gateway/routes管理路由的 API 路径test攻击者自定义的路由 ID用于创建一条新的路由规则攻击者用这个api自定义一个路由载荷里可以定义过滤器而其中的value字段用#{}(SpEL的执行包装器包裹恶意表达式highlighter- vbscript#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\id\}).getInputStream()))}T(java.lang.Runtime)获取 Java 的Runtime类用于执行系统命令.getRuntime()获取Runtime单例对象.exec(new String[]{\id\})执行系统命令id返回Process对象.getInputStream()获取命令执行后的输出流即id命令的结果T(org.springframework.util.StreamUtils).copyToByteArray(...)将输出流读取成字节数组new String(...)将字节数组转换成字符串方便返回和显示#{ ... }SpEL 的执行包装器告诉 Spring 解析并运行里面的代码创建路由成功后payload不会立刻解析需要访问/actuator/gateway/refresh激活所有路由这个时候刚刚创建的test路由就会开始解析SpEL表达式成功执行id命令当攻击者再次访问test路由就能得到webshell执行id后的回显漏洞版本 (v3.1.0) 的代码示意java// 位置: org.springframework.cloud.gateway.support.ShortcutConfigurable public default String getValue(String key, String value) { if (value ! null value.startsWith(#{) value.endsWith(})) { // ❌ 危险StandardEvaluationContext 拥有完整的 SpEL 功能 StandardEvaluationContext context new StandardEvaluationContext(); // 可以调用 Java 类、执行静态方法、访问系统资源... return parser.parseExpression(value).getValue(context, String.class); } return value; }修复版本 (v3.1.1) 的代码示意java// 位置: org.springframework.cloud.gateway.support.ShortcutConfigurable public default String getValue(String key, String value) { if (value ! null value.startsWith(#{) value.endsWith(})) { // ✅ 安全GatewayEvaluationContext 基于 SimpleEvaluationContext // 只支持基本的属性访问禁止执行任意代码 GatewayEvaluationContext context new GatewayEvaluationContext(beanFactory); return parser.parseExpression(value).getValue(context, String.class); } return value; }更详细看Spring Cloud Gateway CVE-2022-22947 漏洞分析|NOSEC安全讯息平台 - 白帽汇安全研究院漏洞复现攻击流程如图