The arsenal

Payloads.

Pick a vulnerability class, learn how to hunt it step by step, grab the payloads that actually work. Curated from PayloadsAllTheThings — the full section is linked under every class.

SSTI

Template injection — user input evaluated as template code server-side, escalating from math probes to full RCE depending on the engine. If a template engine ever renders your raw input, the template language is your command surface.

Severity guide

Critical when RCE is proven (most engines have a chain); medium-low when only the math probe evaluates — but that's still reportable on many programs as template evaluation.

Where to look

entry points to test first

01

Email/DM template features

Custom subject lines, greeting templates — user text rendered through the mail templating engine.

02

CMS & page builders

Custom page/section names, theme variables, marketing landing pages — everything becomes a template.

03

Error pages & PDF reports

Server-side renderers that build pages from user data — often Jinja2 or Freemarker under the hood.

04

Anywhere {{ }} appears

If the app's own output shows template syntax handling (debug pages, preview panes), try it on user input.

05

Chat/support/CRM tools

Salesforce-class platforms and helpdesks render customer strings through template engines constantly.

How to hunt it

in order, start to finish
  1. Detect with a polyglot

    Inject the combined probe ${{<%[%'"}}%\. — any error or odd output means the input is being evaluated as a template.

  2. Fingerprint the engine

    Math probes identify it: {{7*7}}=49 (Jinja2/Twig), ${7*7}=49 (Freemarker), <%= 7*7 %>=49 (ERB), #{7*7}=49 (Ruby).

  3. Map engine → object model

    Jinja2: {{ ''.__class__.__mro__ }} walks Python objects; Twig: _self.env; Freemarker: .exec. Each engine's page on PATh has the exact chain — follow it stepwise, confirming each hop.

  4. Match engine → payload

    Each engine has its own escape-to-RCE chain; the PATh page maps them all.

  5. Automate the identification

    tplmap or sstimap can enumerate the engine and try for an OS shell automatically — point them at the vulnerable parameter with a * marker.

Filter & validation bypasses

when your first tries get blocked
  • 01{{ blocked? Try {% raw %} equivalents, alternative delimiters ${...} / <%= ... %> / #{...} — fingerprint which survives.
  • 02Dots filtered? Jinja2 accepts |attr('__class__') and bracket notation instead of attribute access.
  • 03Underscores blocked? Jinja2 string ops rebuild them: {{ lipsum.__globals__ }} → use attr filters or unicode escapes.
  • 04WAF probes math? String-based probes ({{'a'.upper()}}) evaluate without arithmetic.

Impact ladder

what makes it payable
  1. 01Full RCE — most major engines have documented escape chains.
  2. 02File read/write through the template's object model.
  3. 03Config/secret extraction — environment variables and app settings via template globals.
  4. 04Sandbox escapes count too — even sandboxed engines fall to known bypasses.

Payloads

6 · from PayloadsAllTheThings
${{<%[%'"}}%\.

Polyglot detection probe — breaks every major template engine at once.

{{7*7}}

Jinja2/Twig fingerprint — 49 in the output confirms evaluation.

${7*7}

Freemarker/MVEL fingerprint.

<%= 7*7 %>

ERB (Ruby) fingerprint.

python3 ./sstimap.py -u 'https://example.com/page?name=Vulnerable*' -l 5

sstimap auto-detection with the * marking the injection point.

python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell

tplmap — older tool, still effective on Jinja2-style targets.

Toolstplmap/sstimap/tinja/
Full SSTI section ↗

Payload strings, code and technical terms are shown in English on purpose — payloads must be copied exactly as published.

Payloads originate from PayloadsAllTheThings (MIT) — use them only on programs you're authorized to test.

Payloads — wildhunter