SpringBoot Whitelabel Error page SpEL 注入漏洞是一个发生在 SpringBoot 默认报错页面下的一个漏洞,在处理报错参数时进行了递归处理,并且${}
包围的内容都会被org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
类的resolvePlaceholder
方法当作 SpEL 表达式被解析执行,进而造成漏洞。
这个漏洞报错页面,是开发者自定义了一个视图,在对报错信息展示渲染的时候,判断了模板中每个${和}位置,进而提取参数中的值,正巧页面存在一个 message 占位,该值就是从报错参数中获取的,假设用户的输入中包含${payload},则 SpEL 第一次 message 解析成${payload}之后,解析引擎进行递归,去掉${和}后将 payload 传入 SpEL 引擎,SpEL 引擎将直接对 payload 进行解析,从而触发了漏洞。
影响版本:1.1.0-1.1.12,1.2.0-1.2.7,1.3.0
修复方案:升至1.3.1或以上版本
测试环境:SpringBoot 1.2.0
测试环境下载地址:https://github.com/spring-projects/spring-boot/releases?page=29
payload:http://127.0.0.1:8080/?payload=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x63,0x61,0x6c,
0x63}))}
调试分析
搭建漏洞环境,使用其自己的 sample 搭建一个服务器,然后自己写一个控制器,抛出异常即可。
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.tomcat.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import sample.tomcat.service.HelloWorldService;
@Controller
public class SampleController {
@Autowired
private HelloWorldService helloWorldService;
@RequestMapping("/")
@ResponseBody
public String helloWorld(String payload) throws IllegalAccessException {
//return this.helloWorldService.getHelloMessage();
throw new IllegalAccessException(payload);
}
}
首先分析漏洞触发点,首先这里创建了一个 SpEL 解析器,其次Expression expression = this.parser.parseExpression(name);
解析了用户传入的值,最后使用了getValue()
获取了值,其中StandardEvaluationContext
赋值了context
。将
Context
赋值到this.context
中,然后将 this.template 和 this.resolver 为参数调用replacePlaceholders
方法。
this.template="<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>"
跟进 replacePlaceholders 方法,进入了 PropertyPlaceholderHelper 文件。继续跟进parseStringValue方法,这里就是存在递归,strVal 的值为之前的this.template,将其赋值给 result,然后通过判断 result 中${和}的位置,开始解析 result 中的第一个参数名,并赋值给placeholder,本次的值为"timestamp",然后将 placeholder 作为第一个参数,再次调用本方法(递归调用,以防字符串 placeholder 中包含${})。
跟进递归,由于 placeholder 的值是"timestamp",其中不包含${,导致startindex为-1,故不进入 while 语句,直接到了 return,因此可以发现在递归时,如果第一个参数中不包含${,直接将第一个参数返回。
再次回到之前的点,下一步是调用 resolvePlaceholder 方法,此函数的作用是查找 this.context 中对应。
首先看一下 this.context,发现"timestamp"->"Sat Dec xxxxxxx2025"
继续跟进,发现 value 被赋值成 SpEL 解析后的值,然后 return。
回到 parseStringValue 方法,将经过 SpEL 解析后 return 的值赋值给propVal,由于 propVal !=null,故跳过第一个 if 语句,进入第二个语句,将propVal作为第一个参数再次递归,通过上一次递归我们发现,如果第一个参数中没有${,则直接返回第一个参数。
递归回来后 propVal 的值没变,使用 replace 将 proVal 替换到 result 中的对应的参数位,接着寻找 template 中的下一个参数位,赋值给 startIndex,用于下一次 while 条件判断。
进入第二次循环,这次的参数是 error,和之前的 timestamp 过程一样。
第三次 while 循环,参数是 status,同上。
第四次循环,这次的参数是 message,其中的值是用户输入的。
跟进到第一次递归,防止参数中含有${},由于参数名是 message,故忽略这一步,然后到了 resolvPlaceholder 方法,用于使用 SpEL 表达式引擎解析message的值,跟进。
value 是用户传入的 payload。
其中包含${},是一个 SpEL 表达式,继续跟进,返回到 parseStringValue 方法。
为了防止 propVal 中包含${},再次进行一次递归,下面就是漏洞关键点了,跟进这次递归。
此时 placeholder 的值为去掉${}的 payload,即:new java.lang.ProcessBuilder(new java.lang.String(new byte[]{99,97,108,99})).start(),将 placeholder 作为第一个参数传入 SpEL 解析函数进行解析。
最后触发了 payload。
补丁分析
补丁分析:补丁创建了一个新的NonRecursivePropertyPlaceholderHelper类,用于防止parseStringValue
进行递归解析。补丁 URL:
https://github.com/spring-projects/spring-boot/commit/edb16a13ee33e62b046730a47843cb5dc92054e6
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)