JSForge
Acceder →
← Volver al catálogo
SERVIDORMEDIO En navegador

El Server Va Por Vos

SSRF

// OBJETIVO

Aprovechar que el servidor trae la URL que indicás para alcanzar un recurso interno y leer el endpoint de metadata de la nube.

// ZONA DE ATAQUE

app vulnerable · sandbox aislado

Corre en un iframe de origen opaco: no puede leer este sitio ni tu progreso. Cuando logres el exploit, la flag aparece dentro de la app — copiala y verificala.

// CONSULTÁ

Pistas

    Código vulnerable

    El servidor busca la URL del usuario sin restringir el destino:

    app.post('/api/preview', async (req, res) => {
      const { target } = req.body;
      const r = await fetch(target);          // ← destino controlado por el usuario
      res.json({ ok: true, body: await r.text() });
    });

    Como no hay allowlist ni bloqueo de rangos internos, el atacante hace que el servidor pida direcciones que él no alcanza desde afuera: servicios en localhost, redes privadas (10.0.0.0/8, 192.168.0.0/16) o el endpoint link-local de metadata 169.254.169.254, que en la nube suele exponer credenciales de la instancia. Es SSRF (Server-Side Request Forgery).

    Remediación

    No dejes que el usuario elija un destino arbitrario: validá el esquema, resolvé el host y rechazá todo lo que apunte a rangos internos.

      const { target } = req.body;
    + const url = new URL(target);
    + if (!['http:', 'https:'].includes(url.protocol)) throw new Error('esquema no permitido');
    + const { address } = await dns.promises.lookup(url.hostname);
    + if (isPrivate(address) || isLinkLocal(address)) throw new Error('destino interno bloqueado');
    - const r = await fetch(target);
    + const r = await fetch(url, { redirect: 'error' }); // sin seguir redirects a internos
      res.json({ ok: true, body: await r.text() });

    Por qué funciona: validar el esquema corta file:// y gopher://; resolver el host y rechazar direcciones privadas o link-local impide alcanzar metadata y servicios internos; y redirect: 'error' evita que un 302 a 169.254.169.254 esquive el chequeo. Idealmente, además, usá una allowlist de destinos.

    Verificación

    Se verifica en tu navegador contra un hash. La flag no se envía a ningún lado.