中国联通股票,Java代码审计之SpEL表达式注入,纸上谈兵

频道:新闻世界 日期: 浏览:144

*本文原创作者:Lateink,本文属FreeBuf原创奖赏方案,未经许可制止转载

SpEL 表达式注入

Spring Expression Language(简称 SpEL)是一种功用强大的表达式言语、用于在运行时查询和操作目标图;语法上相似于 Unified EL,但供给了更多的特性,特别是办法调用中国联通股票,Java代码审计之SpEL表达式注入,坐而论道和根本字符串模板函数。SpEL 的诞生是为了给 Spring 社区供给一种能够与 Spring 生态系统一切产品无缝对接,能供给一站式支撑的表达式言语。

SpEL 表达式根本表达式

字面量表达式、联系,逻辑与管用运算表达式、字符串链接及截取表达式、三目运算、正则表达式以及括号优先级表达式;

类相关表达式

类类型表达式、类实例化、instanceof 表达式、变量界说及引证、赋值表达式、自界说函数、目标特点存取及安全导航表达式、目标办法调用、Bean 引证;

调集相关表达式

内联 List、内联数组、调集、字典拜访、列表、字典;

其他表达式

模版表达式

SpEL 根底

在 pom.xml 导入 maven 或是把”org.springframework.expression-3.0.5.RELEASE.jar”增加到类途径中

5.0.8.RELEASE org.springframework spring-expression ${org.springframewor中国联通股票,Java代码审计之SpEL表达式注入,坐而论道k.version}

SpEL 运用办法

SpEL 在求表达式值时一般分为四步,其间第三步可选:首要结构一个解析器,其次解析器解析字符串表达式,在此结构上下文,最终依据上下文得到表达式运算后的值。

ExpressionParser parser = new SpelExpressionParser; Expression expression = parser.parseExpression("('Hello' + ' freebuf').concat(#end)"); EvaluationContext context = new StandardEvaluationContext; context.setVari中国联通股票,Java代码审计之SpEL表达式注入,坐而论道able("end", "!"); System.out.pr冰脸妻主俏丈夫intln(expression.getValue(context));

1.创立解析器:SpEL 运用 ExpressionParser 接口表明解析器,供给 SpelExpressionParser 默许完成;

2.解析表达式:运用 ExpressionParser 的 parseExpression 来解析相应的表达式为 Expression 目标。

3.结构上下文:预备比方变量界说等等表达式需求的上下文数据。

4.求值:经过 Expression 接口的 getValue 办法依据上下文取得表达式值。

SpEL 首要接口

1.ExpressionParser 接口:敏昂兰表明解析器,默许完成是 org.springframework.expression.spel.standard 包中的 SpelExpressionParser 类,运用 parseExpression 办法将字符串表达式转换为 Expression 目标,关于 ParserContext 接口用于界说字符串表达式是不是模板,及模板开端与完毕字符;

public屌丝影楼 interface ExpressionParser { Expression parseExpression(String expressionString); Expression parseExpression(String expressionString, ParserContext context); }

案例 demo

ExpressionParser parser = new SpelExpressionParser; ParserContext parserContext = new ParserContext { @Override public boolean isTempl中国联通股票,Java代码审计之SpEL表达式注入,坐而论道ate { return true; } @Override public String getExpressionPrefix { return "#{"; } @Override public String getExpressionSuffix { return "}"; } }; String template = "#{'hello '}#{'freebuf!'}"; Expression expression = parser.parseExpression(template, parserContext); System.out.println(expression.getValue);

演示的是运用 ParserContext 的状况,此处界说了 ParserContext 完成:界说表达式是模块,表达式前缀为「#{」,后缀为「}」;运用 parseExpression 解析时传入的模板有必要以「#{」最初,以「}」结束。

默许传入的字符串表达式不是模板办法,如之前演示的 Hello World。

EvaluationContext 接口:表明上下文环境,默许完成是 org.springframework.expression.spel.support 包中的 StandardEvaluationContext 类,运用 setRootObject 办法来设置根目标,运用 setVariable 办法来注册自界说变量,运用 registerFunction 来注册自界说函数等等。

Expression 接口:表明表达式目标,默许完成是 org.springframework.expression.spel.standard 包中的 SpelExpression,供给 getValue 办法用于获取表达式值,供给 setValue 办法用于设置目标值。

SpEL 语法 – 类相关表达式

类类型表达式:运用”T(Type海角0号)”来表明 java.lang.Class 实例,”Type”有必要是类全限定名,”java.lang”包在外,即该包下的类能够不指定包名;运用类类型表达式还能够进行拜访类静态办法及类静态字段。

详细运用办法上党鼓书长子平话大全

ExpressionParser parser = new SpelExpressionParser; // java.lang 包类拜访 Class result1 欢渡国庆= parser.parseExpression("T(String)").getValue(Class.class); System.out.printmilkycatln(result1); //其他包类拜访 String expression2 = "T(java.lang.Runtime).getRuntime.exec('open /Applications/Calculator.app')"; Class result2 = parser.parseExpression(expression2).getValue(Class.class); System.out.println(result2); //类静态字段拜访 int result3 = parser.parseExpression("T(Integer).MAX_VALUE").getVal母亲亲身ue(int.class); System.out.println(result3); //类静态办法调用 int result4 = parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class); System.ou脱狱者t.println(result4);

类实例化:类实例化相同运用 java 要害字「new」,类名有必要是全限定名,但 java.lang 包内的类型在外,如 String、Integer。

instanceof 表达式:SpEL 支撑 instanceo中国联通股票,Java代码审计之SpEL表达式注入,坐而论道f 运算符,跟 Java 内运用同义;如”‘haha’ instanceof T(String)”将回来 true。

变量界说以及引证:变量界说经过 Evalua中国联通股票,Java代码审计之SpEL表达式注入,坐而论道tionContext 接口的 setVariable(variableName, value) 办法界说;在表达式中运用”#variableName”引证;除了引证自界说变量,SpE 还答应引证根目标及当时上下文目标,运用”#roo陈蓉老公t”引证根目标,运用”#this”引证当时上下文目标;

自界说函数:现在只支撑类静态办法注册为自界说函数;SpEL 运用 StandardEvaluationContext 的 registerFunction 办法进行注册自界说函数,其实完全能够运用 setVariable 替代,两者其实实质是相同的

这儿拿 Spring Message 长途指令履行缝隙来作为比如

环境建立

git clone https://github.com/spring-guides/gs-messaging-stomp-websocket git checkout 6958af0b02bf05282673826b73cd7a85e84c12d3

拿到项目代码,大局查找一下 org.springframework.expression.spel.standard,发现 DefaultSubionRegistry.java 文件处有导入。

再查找一下 SpelExpressionParser

往下跟进发现如下要害代码,详细剖析看代码注释

@Override protected void addSubionInternal( S陈誉之tring sessionId, String subsId, String destination, Message message) { Expression expression = null; MessageHeaders headers = message.getHeaders; // 这儿能够看出 SpEL 表达式 expression 是从 headers 中的 selector 字段中取出来 String selector = SimpMe石萱ssageHeaderAccessor.getFirstNativeHeader(getSelectorHeaderName, headers); if (selector != null) { try { //生成 expression 目标 expression = this.expressionParser.parseExpression(selector); this.selectorHeaderInUse = true; if (logger.isTraceEnabled) { logger.trace("Subion selector: [" + selector + "]"); } } catch (Throwable ex) { if (logger.isDebugEnabled) { logger.debug("Failed to parse selector: " + selector, ex); } } } // expression 传入 addSubion 这个函数里边,即存放在 this.subionRegistry this.sub一角书屋ionRegistry.addSubion(sessionId, subsId, destination, expression); this.destinationCache.updateAfterNewSubion(destination, sessionId, su经典十字绣大全bsId); }

再查找一下 this.subionRegistry,看看有没有调用传进去的 expression。

然后发现了!

在这儿调用了 this.subionRegist叶七七ry.getSubions(sessionId) 并从中取出 info->sub-> expression。

最要害的是,这儿直接调用了 expression.getValue!这说明如果能操控 SpEL 的表达式,就能直接指令履行!

再来看看这个 filterSubions 函数在哪里调用。从函数的调用回溯追寻调用链如下:

filterSubions -> findSubionsInternal -> findSubions -> sendMessageToSubscribers

sendMessageToSubscribers 即发送音讯的功用

回忆一下整个流程,SpEL 表达式从 headers 中 selector 获取,即发送恳求时增加 selector 到恳求的 header 即可传入,然后生成 expression 目标传入 this.subionRegistry,然后当发送音讯的时分,最终会直接从 this.subionRegistry 取出并调用 expression.getValue 履行咱们传入的 SpEL 表中国联通股票,Java代码审计之SpEL表达式注入,坐而论道达式。

验证进程,在 expression.getValue 这儿打个断点,看看发送音讯是否会阻拦并检查调用链是否如上述剖析相同。

Bingo!

简略总结一下 SpEL 表达式注入的剖析思路,能够先大局查找 org.springframework.expression.spel.standard, 或是 expression.getValue、expr幽姌之往生ession.setValue,定位到详细缝隙代码,再剖析传入的参数能不能运用,最终再追寻参数来历,看看是否可控。Spring Data Commons Remote Code Execution 的 SpEL 注重生之长征小赤军入导致的代码履行相同能够用相似的思路剖析。

缝隙修正

SimpleEvaluationContext、StandardEvaluationContext 重生之炮灰乡村媳是 SpEL 供给的两个 EvaluationContext

SimpleEvaluationContext - 针对不需求 SpEL 言语语法的悉数规模而且应该遭到有意约束的表达式类别,揭露 Spal 言语特性和装备选项的子集。

StandardEvaluationContext - 揭露全套 SpEL 言语功用和装备选项。您能够运用它来指定默许的根目标并装备每个可用的评价相关战略。

SimpleEvaluationContext 旨在仅支撑 SpEL 言语语法的一个子集。它不包含 Java 类型引证,结构函数和 bean 引证;所以最直接的修正办法是运用 SimpleEvaluationContext 替换 StandardEvaluationContext。

这是我个人学习代码审计进程中的小总结,或许逻辑性相对来说没那么谨慎,可是个人觉得这是一个比较通俗易懂的剖析办法,不喜勿喷。

参阅文章:

*本文原创作者:Lateink,本文属FreeBuf原创奖赏方案,未经许可制止转载

石凉 58
声明:该文观念仅代表作者自己,搜狐号系信息发布渠道,搜狐仅供给信息存储空间效劳。