ssti-server-side-template-injection

SSTI playbook. Use when template expressions, server-side rendering, preview features, or templating engines may evaluate attacker-controlled content.

By yaklang · 3,018 installs

npx skills add yaklang/hack-skills --skill ssti-server-side-template-injection

Source repository · Upstream listing

SKILL: Server Side Template Injection (SSTI) — Expert Attack Playbook AI LOAD INSTRUCTION : Expert SSTI techniques. Covers polyglot detection probes, engine fingerprinting, Jinja2/FreeMarker/Twig/ERB RCE chains, client side Angular SSTI, and bypass techniques. Base models often miss sandbox escape MRO chains and non Jinja2 engines. For PHP CMS template eval, Jira SSTI, Confluence OGNL, and Spring Cloud Gateway SpEL, load the companion [SCENARIOS.md](./SCENARIOS.md). 0. RELATED ROUTING Before using full engine specific exploitation, you can first load: First use the polyglot probe sequence at the top of this file for low noise fingerprinting [expression language injection](../expression language injection/SKILL.md) when ${7 7} or %{7 7} resolves in Java (SpEL/OGNL) — different attack surface from template engines Extended Scenarios Also load [SCENARIOS.md](./SCENARIOS.md) when you need: Maccms 8.x PHP template eval — {if A:phpinfo()}{endif A} in vod search , base64 bypass for webshell write Jira CVE 2019 11581 — "Contact Administrators" form → Velocity template injection → command output in admin email Spring Cloud Gateway SpEL (CVE 2022 22947) — actuator route injection with StreamUtils.copyToByteArray for output capture Struts2 OGNL S2 045 (CVE 2017 5638) — Content Type header OGNL injection with memberAccess / OgnlUtil blacklist clear Confluence OGNL CVE 2021 26084 — createpage entervariables.action with \u0027 unicode bypass SSTI vs EL injection disambiguation guide Additional template engines: ASP.NET Razor, Elixir EEx, PHP Smarty/Latte/Blade, JS Pug/Handlebars/Nunjucks/EJS/Lodash + universal detection + blind SSTI + Flask PIN calculation SCENARIOS.md reference (§7–§11): For expanded payloads and engine specific notes on Razor, EEx/LEEx/HEEx, PHP stacks, JavaScript template engines, the universal polyglot probe, mathematical fingerprinting, blind SSTI (boolean / time / OOB), and Flask debug PIN prerequisites, see [SCENARIOS.md](./SCENARIOS.md). This skill keeps a short checklist in §13–§15. Engine Payloads Reference For extended engine specific fingerprinting, payload matrices (Jinja2, Twig, Freemarker, Velocity, Pebble, Mako, Slim, Handlebars, Thymeleaf, Smarty, ERB, Jade/Pug), and blind SSTI detection techniques (timing based, DNS based), see [ENGINE PAYLOADS.md](./ENGINE PAYLOADS.md). Universal detection & blind SSTI (pointer) Use the polyglot payload and math probes in §1 and §13 first; when you need fuller blind test patterns and per engine examples (including non Python stacks), follow [SCENARIOS.md](./SCENARIOS.md) §11 and cross check §14 here for technique names (boolean, time, OOB, error based). 1. DETECTION — POLYGLOT PROBE SEQUENCE First test: distinguish SSTI from XSS. Send these probes and check if math is evaluated server side: Jinja2 vs Twig disambiguation : Safe detection probe (no math, just boolean): 2. ENGINE TO LANGUAGE MAPPING Template Engine Language Framework Jinja2 Python Flask, FastAPI Django Templates Python Django Mako Python Pyramid Twig PHP Symfony, Laravel Smarty PHP Various FreeMarker Java Spring MVC Velocity Java Various Java Pebble Java Various Java Thymeleaf Java Spring Boot ERB Ruby Rails Slim / Haml Ruby Rails Jade / Pug Node.js Express Handlebars Node.js Express Tornado Python Tornado Identifying language from errors → then narrow to template engine. 3. JINJA2 (PYTHON FLASK) — RCE CHAINS Chain 1: os module via globals Chain 2: MRO subclass traversal (sandbox escape) Chain 3: request object globals (works when config blocked) (Uses hex encoding to avoid filtering) Chain 4: lipsum function globals (Flask built in) Chain 5: cycler object Finding correct subprocess index dynamically: 4. JINJA2 SANDBOX BYPASS TECHNIQUES When (underscore) is blocked: When . (dot) is blocked: When keywords (class, mro) are blocked: Use hex/unicode in attr() : When output encoding strips HTML entities: Use safe filter to prevent auto escaping. 5. FREEMARKER (JAVA) — RCE Execute Command via freemarker.template.utility.Execute Alternative via ObjectConstructor: 6. TWIG (PHP) — RCE 7. VELOCITY (JAVA) — RCE Or more directly: 8. ERB (RUBY RAILS) — RCE 9. THYMELEAF (JAVA SPRING) — RCE Thymeleaf with Spring EL (SpEL): 10. CLIENT SIDE TEMPLATE INJECTION (AngularJS) When AngularJS is used client side and user data flows into template expressions: Detection : send {{1+1}} — if page shows 2 , AngularJS evaluates expressions in the DOM. 11. SSTI → FULL RCE PATH Post RCE pivot : 1. Read /proc/self/environ — env vars with credentials 2. Read application config files — DB passwords, API keys 3. cat ~/.aws/credentials — cloud credentials 4. Reverse shell for persistence 12. COMMON INJECTION ENTRY POINTS Where user data enters templates: URL path: https://site.com/home?name={{7 7}} Query parameters: ?message=Hello HTML forms: profile name, bio, content fields Error pages: 404 Not Found: /PAYLOAD Email templates: name in password reset emails Inline template rendering: render template string(user input) Most dangerous : render template string() in Flask — entire user input used as template. 13. UNIVERSAL DETECTION PAYLOADS Polyglot probe that triggers errors or evaluation in many engines: Mathematical probes for blind/error confirmation: Error based engine fingerprint (parser/stack traces often name the engine): 14. BLIND SSTI TECHNIQUES Boolean based : Compare (3 4/2) vs 3 )2(/4 — if the first resolves and the second errors, evaluation is likely Time based : {{sleep(5)}} or the engine specific equivalent for delay OOB : DNS/HTTP callback via template expressions when direct output is not visible Error based : Force different error messages based on true/false conditions 15. FLASK PIN CALCULATION When Flask debug mode (Werkzeug debugger) is exposed but PIN protected , the PIN is derived from host specific values. Typical inputs for public PIN calculation scripts: 1. username — from /etc/passwd (the user running the Flask process) 2. Module name — often flask.app or Flask 3. Application path — app.py or the real main filename 4. MAC address — e.g. /sys/class/net/eth0/address , converted to decimal as Werkzeug expects 5. Machine ID — /etc/machine id , or /proc/sys/kernel/random/boot id combined with the first line of /proc/self/cgroup per Werkzeug’s algorithm 6. Compute PIN — use established open source PIN calculators that implement the same algorithm from these values Use only on systems you are authorized to test; obtaining these values implies prior access or an additional info disclosure vector.