|9 min de lectura|Yvann Lièvre

Escribir una plantilla Nuclei para una CVE: del aviso a una plantilla que se dispara (sin falsos positivos)

Sale una CVE, el aviso de seguridad es público, pero aún no existe ninguna plantilla Nuclei. Aquí tienes cómo escribir una limpia: partir del hecho, construir los matchers, y sobre todo demostrar que se dispara en un objetivo vulnerable sin gritar en uno parcheado.

NucleiCVEDetectionVulnerability Scanning
Escribir una plantilla Nuclei para una CVE: del aviso a una plantilla que se dispara (sin falsos positivos)

Se publica una CVE crítica un viernes por la noche. El aviso describe el fallo, la versión afectada, la ruta vulnerable. La pregunta ya no es «¿estoy afectado?» sino «¿cuántos de mis activos lo están, ahora mismo?». Nuclei es la herramienta de referencia para responder a escala: un motor rápido, plantillas YAML legibles, versionables como código. El problema es que, cuando cae la CVE, la plantilla oficial todavía no existe, llegará en unos días, a veces unas semanas. Ese retraso es tu ventana de exposición.

Escribir la plantilla tú mismo cierra ese hueco. Pero una plantilla mal escrita es peor que ninguna: falla la versión vulnerable (falso negativo, te crees a salvo) o grita sobre una versión ya corregida (falso positivo, ahogas al equipo en ruido). Este artículo muestra cómo escribir una que se dispare con precisión, y sobre todo cómo demostrarlo.

Por qué no esperar simplemente la plantilla oficial

Tres razones para saber hacerlo tú mismo:

  • El desfase. Entre la publicación de una CVE y la llegada de una plantilla pública transcurre un tiempo variable. En un fallo activamente explotado (una entrada del catálogo CISA KEV), ese retraso es exactamente la ventana en la que los atacantes también escanean.
  • Tus aplicaciones propias. Ningún proyecto comunitario cubrirá tu ERP interno, tu portal a medida o esa appliance de nicho. La detección en ese perímetro no la escribirá nadie por ti.
  • La priorización. No puedes escribir una plantilla para las 40 000 CVE del año. Saber hacerlo rápido para el puñado que importa (las explotadas, expuestas, en tus activos críticos) es una competencia de detection engineering, no un lujo.

La anatomía de una plantilla Nuclei

Una plantilla es un fichero YAML en dos partes: los metadatos (info) y la lógica (la petición más los matchers). Aquí el esqueleto:

id: cve-2024-0000-config-disclosure
 
info:
  name: "ACME Portal < 4.2 - Divulgación de configuración no autenticada"
  author: tu-equipo
  severity: high
  description: |
    ACME Portal antes de 4.2 expone /api/v1/config sin autenticación,
    revelando las credenciales de la base de datos y las claves de API.
  classification:
    cve-id: CVE-2024-0000
    cvss-score: 8.6
  tags: cve,cve2024,acme,exposure
 
http:
  - method: GET
    path:
      - "{{BaseURL}}/api/v1/config"
    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
      - type: word
        part: body
        words:
          - '"db_password"'
          - '"api_key"'
        condition: and

(El ejemplo es ilustrativo: importa más el principio que la CVE elegida.) Cada bloque tiene un papel. El id es único y descriptivo. El bloque info lleva la severidad y la classification (el cve-id, la puntuación CVSS), no es decoración: es lo que permitirá clasificar, correlacionar y priorizar después. La sección http describe qué se envía y qué prueba la vulnerabilidad.

Partir del hecho, no del proof-of-concept

Este es el punto más importante, y el más a menudo omitido. En GitHub casi siempre circula un PoC de explotación antes que la plantilla. La tentación es copiarlo. No lo hagas, por dos razones.

Primero, el rigor jurídico: un PoC publicado sin licencia explícita es «todos los derechos reservados» por defecto. Copiarlo en una plantilla que compartes o revendes es un problema. En cambio, el hecho descrito por el aviso («la versión X expone la ruta Y que devuelve la cadena Z») no pertenece a nadie. Una firma de detección es obra tuya, igual que una firma de antivirus no hereda los derechos del malware que detecta.

Segundo, la calidad: un PoC busca explotar, una plantilla busca constatar sin peligro. No quieres depositar un webshell para probar una RCE; quieres el signo más ligero y fiable de que el fallo está ahí. El aviso te da exactamente ese signo: la ruta, el marcador de versión, la firma de respuesta. Es tu materia prima.

Construir los matchers, del más grosero al más preciso

Un matcher que devuelve «vulnerable» con demasiada facilidad es la trampa número uno. Tomemos tres niveles:

Nivel 1: el código de estado solo. status: 200 en /api/v1/config. Insuficiente: una versión parcheada puede devolver 200 con una página vacía o un mensaje de error. Un estado no prueba la vulnerabilidad, prueba que la ruta existe.

Nivel 2: el estado más una palabra clave. Se añade la presencia de "db_password" en el cuerpo. Mucho mejor: solo se dispara si la respuesta contiene realmente el dato filtrado. El matchers-condition: and impone que ambas condiciones sean ciertas.

Nivel 3: la discriminación de versión. El caso sutil. Si la versión 4.2 (corregida) aún devuelve la clave pero vacía, el nivel 2 produce un falso positivo. Hace falta entonces un matcher regex que capture un valor no vacío, o leer el marcador de versión en una cabecera. Aquí se juega la diferencia entre una plantilla que hace ruido y una en la que tu equipo confía.

Para un fallo ciego (sin respuesta directa observable, una inyección out-of-band, un SSRF), Nuclei ofrece interactsh: la plantilla desencadena una interacción de red hacia un servidor de control y confirma la vulnerabilidad por esa llamada, sin explotar nunca el objetivo.

Validar no basta: hay que demostrar

Nuclei ofrece un control integrado:

nuclei -validate -t cve-2024-0000-config-disclosure.yaml

Cuidado con el malentendido: -validate verifica la sintaxis, no la eficacia. Una plantilla perfectamente válida puede no detectar nada, o detectarlo todo. La validación sintáctica es necesaria, nunca suficiente.

La verdadera prueba es empírica y se reduce a dos tests:

  1. ¿La plantilla se dispara en un objetivo vulnerable? Levanta la aplicación en su versión vulnerable (un contenedor Docker de la versión correcta sirve muy bien) y lanza la plantilla sobre ella. Si no se dispara, es inútil.
  2. ¿Permanece silenciosa en un objetivo parcheado? Levanta la versión corregida y relanza. Si aún se dispara, tienes un falso positivo, el peor resultado, porque erosiona la confianza en todas tus alertas.

Una plantilla que ha pasado ambos tests vale infinitamente más que una simplemente «válida». Es la diferencia entre «compila» y «funciona, demostrado».

Las trampas que salen caras

  • El matcher demasiado genérico. Dispararse sobre un banner de versión («Server: ACME/4.1») es frágil: el banner se maquilla, se retira o permanece tras un parche retroportado. Prefiere siempre el comportamiento vulnerable observable a la autodeclaración del software.
  • La versión corregida olvidada. El test «parcheado» no es opcional. La mitad de los falsos positivos vienen de ahí.
  • El duplicado. Antes de conservar tu plantilla, comprueba que no exista ya un equivalente aguas arriba. La herramienta cent agrega y deduplica colecciones de plantillas, útil para no mantener por duplicado lo que la comunidad ya cubre.
  • Las clasificaciones descuidadas. Rellena cve-id, cvss-score, severity. Es lo que hará tus resultados utilizables, clasificables por gravedad, correlacionables con tus otras fuentes.

Priorizar: no todas las CVE son iguales

Escribir una plantilla tiene un coste. Invertirlo en los fallos correctos lo cambia todo. Dos fuentes públicas y gratuitas orientan el esfuerzo:

  • CISA KEV (Known Exploited Vulnerabilities): el catálogo de fallos activamente explotados. Una CVE que figura ahí es una urgencia, no una hipótesis.
  • EPSS (Exploit Prediction Scoring System): una probabilidad de explotación a 30 días. Útil para arbitrar entre dos fallos antes de que se exploten.

Cruzar «esta CVE está en KEV» con «afecta a un activo expuesto mío» da una lista corta y accionable: esas son las plantillas que escribir primero.

En resumen

Escribir una buena plantilla Nuclei para una CVE es un método, no improvisación: partir del hecho descrito por el aviso (no del PoC), construir el matcher más preciso posible (no solo un estado), y demostrar empíricamente que se dispara en lo vulnerable y calla en lo parcheado. El resto (validación sintáctica, clasificaciones, deduplicación) es higiene.

Es precisamente la disciplina que aplicamos a escala en el feed Nuclei de ThreatClaw: cada plantilla se valida en el motor real, se prioriza por KEV y EPSS, y se entrega como respuesta rápida sobre los fallos que importan. Cuando una CVE crítica cae un viernes por la noche, la ventana de exposición ya está cubierta, no tienes que escribirla tú mismo bajo presión.

Artículos relacionados