引言
在练习靶场的时候遇到了spel表达式注入的题目,这篇文章主要是学习总结一下spel表达式的相关知识点,然后进一步学习spel表达式相关漏洞,了解如何利用改漏洞或者代码审计找到相关漏洞。
作为初学者,主要的学习要点如下:
- 什么是spel表达式, 如何使用?
- 如何利用spel表达式漏洞,以及相关的绕过方式。
- spel表达式漏洞的防护。
学习spel表达式
笔者一开始想直接从spel表达式的漏洞入手,可是发现许多描述都不理解,我的java用的不是很多,也不知道表达式的作用是啥,于是我们先学习一下spel表达式使用的知识,再学习相关漏洞。
spel表达式,全称为Spring Expression language,直观的理解,它可以将字符串看作表达式并运行, 这个字符串可以是硬编码的字符串,也可以是外部传递过来的参数。 如果是由外部传过来的,就需要注意是否有可能造成表达式注入问题。例如,可以执行恶意构造的表达式或者执行类实例对象。
我们可以创建一个demo实例,来实践运行一下spel表达式。具体如下:
在IDEA中新建maven工程。
其中pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>spel</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>5.1.9.RELEASE</version></dependency></dependencies></project>
class文件内容如下,可自行编辑spel表达式进行尝试。
importorg.springframework.expression.EvaluationContext;importorg.springframework.expression.Expression;importorg.springframework.expression.ExpressionParser;importorg.springframework.expression.spel.standard.SpelExpressionParser;importorg.springframework.expression.spel.support.StandardEvaluationContext;//import org.springframeworkpublicclassSpELTest{publicstaticvoidmain(String[] args){// 创建解析器:SpEL 使用 ExpressionParser 接口表示解析器,提供 SpelExpressionParser 默认实现ExpressionParser parser =newSpelExpressionParser();// 解析表达式:使用 ExpressionParser 的 parseExpression 来解析相应的表达式为 Expression 对象Expression expression = parser.parseExpression("('Hello' + ' FreeBuf').concat(#end)");// 构造上下文:准备比如变量定义等等表达式需要的上下文数据EvaluationContext context =newStandardEvaluationContext();// 这里, #end 可以看作一个变量,变量的值为"!"
context.setVariable("end","!");// 求值:通过 Expression 接口的 getValue 方法根据上下文获得表达式值System.out.println(expression.getValue(context));}}
这里分享几个表达式的使用:
- 字符串,数字等表达式
double double1 = parser.parseExpression("1.1E+2").getValue(double.class);int hex1 = parser.parseExpression("0xa").getValue(Integer.class);long hex2 = parser.parseExpression("0xaL").getValue(long.class);boolean true1 = parser.parseExpression("true").getValue(boolean.class);boolean false1 = parser.parseExpression("false").getValue(boolean.class);Object null1 = parser.parseExpression("null").getValue(Object.class);
- 算数运算表达式
类型示例加减乘除int result1 = parser.parseExpression("1+2-3*4/2").getValue(Integer.class);
- 关系表达式
boolean result3 = parser.parseExpression("2>1 and (NOT true or NOT false)").getValue(boolean.class);boolean result4 = parser.parseExpression("2>1 && (NOT true || NOT false)").getValue(boolean.class);
- 类类型表达式
ExpressionParser parser =newSpelExpressionParser();//java.lang包类访问Class<String> result1 = parser.parseExpression("T(String)").getValue(Class.class);System.out.println(result1);//其他包类访问String expression2 ="T(com.javacode2018.spel.SpelTest)";Class<SpelTest> value = parser.parseExpression(expression2).getValue(Class.class);System.out.println(value ==SpelTest.class);//类静态字段访问int result3 = parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class);System.out.println(result3 ==Integer.MAX_VALUE);//类静态方法调用int result4 = parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class);System.out.println(result4);
靶场练习:spel表达式注入漏洞
spel表达式如果接收外来的参数, 一定要考虑对于非法输入的过滤, 否则会产生注入漏洞。 后续将会分享一下具体的靶场实例。
漏洞防护
和sql注入漏洞类似, 严格过滤不信任的数据。
参考文档
版权归原作者 Coder_preston 所有, 如有侵权,请联系我们删除。