Instalación de Nuclei: Escáner de Vulnerabilidades

Nuclei es un escáner de vulnerabilidades de código abierto basado en plantillas YAML que permite detectar miles de vulnerabilidades conocidas en aplicaciones web, APIs, redes e infraestructura con una velocidad y precisión excepcionales. Con más de 9000 plantillas comunitarias actualizadas continuamente y soporte para integración en pipelines CI/CD, Nuclei es la herramienta de referencia para security testing automatizado en Linux.

Requisitos Previos

  • Servidor Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)
  • Go 1.21+ (para instalación desde el código fuente)
  • Mínimo 1 GB de RAM
  • Conexión a internet para descargar las plantillas
  • Permiso explícito de los objetivos antes de escanear (obligatorio legalmente)

Instalación de Nuclei

# Método 1: Instalación con Go (recomendado - siempre la versión más reciente)
# Instalar Go si no está disponible
wget https://go.dev/dl/go1.22.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.22.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> ~/.bashrc
source ~/.bashrc

# Instalar Nuclei
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest

# Verificar la instalación
nuclei -version

# Método 2: Descargar el binario precompilado
NUCLEI_VERSION=$(curl -s https://api.github.com/repos/projectdiscovery/nuclei/releases/latest \
  | grep '"tag_name"' | cut -d'"' -f4)

wget "https://github.com/projectdiscovery/nuclei/releases/download/${NUCLEI_VERSION}/nuclei_${NUCLEI_VERSION#v}_linux_amd64.zip"
unzip nuclei_*.zip
sudo mv nuclei /usr/local/bin/
chmod +x /usr/local/bin/nuclei

# Actualizar las plantillas de la comunidad
nuclei -update-templates

# Ver las plantillas instaladas
ls ~/.local/nuclei-templates/
nuclei -list  # Listar todas las plantillas disponibles

Uso de Plantillas

# Escaneo básico con todas las plantillas
nuclei -u https://tudominio.com

# Escaneo con categorías específicas de plantillas
# Vulnerabilidades conocidas (CVEs)
nuclei -u https://tudominio.com -t cves/

# Configuraciones incorrectas de seguridad
nuclei -u https://tudominio.com -t misconfiguration/

# Paneles expuestos (Admin panels, debug interfaces)
nuclei -u https://tudominio.com -t exposed-panels/

# Tecnologías identificadas (fingerprinting)
nuclei -u https://tudominio.com -t technologies/

# Escaneo solo con plantillas de severidad alta y crítica
nuclei -u https://tudominio.com -severity high,critical

# Excluir plantillas por severidad (excluir informativas)
nuclei -u https://tudominio.com -exclude-severity info,low

# Escanear múltiples objetivos desde un fichero
cat > /tmp/objetivos.txt << 'EOF'
https://app1.empresa.com
https://app2.empresa.com
https://api.empresa.com
EOF

nuclei -list /tmp/objetivos.txt -t cves/ -severity critical,high

# Escanear un rango de IPs (solo con autorización)
nuclei -u "192.168.1.0/24" -t network/ -severity critical

# Escaneo silencioso - solo mostrar resultados
nuclei -u https://tudominio.com -silent

# Guardar resultados en JSON para procesamiento posterior
nuclei -u https://tudominio.com \
  -json-export /tmp/nuclei-results.json \
  -severity high,critical

Creación de Plantillas Personalizadas

Las plantillas de Nuclei se escriben en YAML:

# Crear directorio para plantillas personalizadas
mkdir -p ~/.local/nuclei-templates/custom/

# Plantilla básica para detectar una vulnerabilidad específica
cat > ~/.local/nuclei-templates/custom/check-admin-panel.yaml << 'EOF'
id: check-admin-panel-exposed

info:
  name: Panel de Administración Expuesto
  author: tu-nombre
  severity: medium
  description: Detecta paneles de administración accesibles públicamente
  tags: exposure,admin

http:
  - method: GET
    path:
      - "{{BaseURL}}/admin"
      - "{{BaseURL}}/admin/"
      - "{{BaseURL}}/administrator"
      - "{{BaseURL}}/wp-admin"
      - "{{BaseURL}}/panel"

    matchers-condition: and
    matchers:
      # La respuesta debe ser exitosa (no 404)
      - type: status
        status:
          - 200
          - 302

      # Y contener palabras clave típicas de un admin panel
      - type: word
        words:
          - "admin"
          - "login"
          - "dashboard"
          - "panel"
        condition: or
        case-insensitive: true

      # No debe estar detrás de autenticación (sin redirección a login)
      - type: word
        words:
          - "Authorization Required"
          - "401 Unauthorized"
        negative: true
EOF

Plantilla avanzada con extracción de datos:

# ~/.local/nuclei-templates/custom/check-api-keys.yaml
id: exposed-api-keys-in-js

info:
  name: Claves API Expuestas en JavaScript
  author: tu-nombre
  severity: high
  description: Detecta claves API hardcodeadas en ficheros JavaScript
  tags: exposure,api,secrets

http:
  - method: GET
    path:
      - "{{BaseURL}}/static/js/app.js"
      - "{{BaseURL}}/js/main.js"
      - "{{BaseURL}}/assets/js/bundle.js"

    matchers-condition: or
    matchers:
      # Patrón de API key de AWS
      - type: regex
        regex:
          - 'AKIA[0-9A-Z]{16}'
        part: body

      # Token de GitHub
      - type: regex
        regex:
          - 'ghp_[A-Za-z0-9]{36}'
          - 'github_pat_[A-Za-z0-9_]{82}'
        part: body

      # Token de Stripe
      - type: regex
        regex:
          - 'sk_live_[A-Za-z0-9]{24,}'
        part: body

    extractors:
      - type: regex
        regex:
          - 'AKIA[0-9A-Z]{16}'
          - 'sk_live_[A-Za-z0-9]{24,}'
        part: body
# Ejecutar la plantilla personalizada
nuclei -u https://tudominio.com \
  -t ~/.local/nuclei-templates/custom/ \
  -v

# Validar la sintaxis de la plantilla
nuclei -validate -t ~/.local/nuclei-templates/custom/check-admin-panel.yaml

Estrategias de Escaneo

# Escaneo rápido de reconocimiento (fase 1)
nuclei -u https://tudominio.com \
  -t technologies/ \
  -t exposures/configs/ \
  -silent \
  -o /tmp/recon-results.txt

# Escaneo de vulnerabilidades conocidas (fase 2)
nuclei -u https://tudominio.com \
  -t cves/ \
  -severity critical,high,medium \
  -rate-limit 10 \        # 10 peticiones por segundo (ser respetuoso)
  -timeout 10 \
  -o /tmp/vuln-results.txt

# Escaneo profundo de una aplicación web específica
nuclei -u https://tudominio.com \
  -t vulnerabilities/ \
  -t misconfiguration/ \
  -t default-logins/ \
  -headers "Cookie: session=TU_TOKEN_DE_SESION" \  # Escaneo autenticado
  -severity medium,high,critical \
  -json-export /tmp/deep-scan.json

# Escaneo de una red interna completa (desde dentro de la red)
nuclei \
  -list /tmp/hosts-internos.txt \
  -t network/ \
  -t misconfiguration/ \
  -rate-limit 5 \
  -bulk-size 10 \         # Número de hosts procesados en paralelo
  -concurrency 25 \       # Número de plantillas paralelas por host
  -o /tmp/internal-scan.txt

# Procesar resultados JSON
cat /tmp/deep-scan.json | jq -r '.[] | "\(.severity) | \(.name) | \(.matched)"' | sort

Integración con CI/CD

# .gitea/workflows/security-scan.yml (o .github/workflows/)
name: Escaneo de Seguridad

on:
  push:
    branches: [main]
  schedule:
    - cron: '0 2 * * 1'  # Cada lunes a las 2am

jobs:
  nuclei-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Instalar Nuclei
        run: |
          go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
          nuclei -update-templates

      - name: Escaneo de staging
        run: |
          nuclei \
            -u ${{ vars.STAGING_URL }} \
            -t cves/ \
            -t misconfiguration/ \
            -severity critical,high \
            -json-export nuclei-results.json \
            -exit-code  # Salir con código de error si hay vulnerabilidades críticas

      - name: Analizar resultados
        if: always()
        run: |
          if [ -f nuclei-results.json ]; then
            CRITICAL=$(cat nuclei-results.json | jq '[.[] | select(.severity == "critical")] | length')
            HIGH=$(cat nuclei-results.json | jq '[.[] | select(.severity == "high")] | length')
            echo "Vulnerabilidades Críticas: $CRITICAL"
            echo "Vulnerabilidades Altas: $HIGH"

            if [ "$CRITICAL" -gt "0" ]; then
              echo "::error::Se encontraron $CRITICAL vulnerabilidades críticas"
              exit 1
            fi
          fi

      - name: Subir reporte
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: nuclei-security-report
          path: nuclei-results.json

Flujo de Divulgación Responsable

# Script para gestionar el proceso de divulgación responsable
cat > /usr/local/bin/responsible-disclosure.sh << 'SCRIPT'
#!/bin/bash
# Flujo de divulgación responsable con Nuclei

TARGET="$1"
COMPANY="$2"
OUTPUT_DIR="/tmp/disclosure/${COMPANY}"

# Verificar que tienes autorización (paso obligatorio)
echo "¿Tienes autorización explícita para escanear $TARGET? (sí/no)"
read CONFIRMED
if [ "$CONFIRMED" != "sí" ]; then
    echo "Escaneo cancelado. Solo escanea sistemas con autorización explícita."
    exit 1
fi

mkdir -p "$OUTPUT_DIR"

# Fase 1: Reconocimiento no intrusivo
echo "[+] Fase 1: Reconocimiento..."
nuclei -u "$TARGET" \
  -t technologies/ \
  -t fingerprints/ \
  -silent \
  -json-export "$OUTPUT_DIR/01_recon.json"

# Fase 2: Detección de vulnerabilidades
echo "[+] Fase 2: Detección de vulnerabilidades..."
nuclei -u "$TARGET" \
  -t cves/ \
  -t misconfiguration/ \
  -severity critical,high,medium \
  -rate-limit 5 \
  -json-export "$OUTPUT_DIR/02_vulnerabilities.json"

# Fase 3: Generar reporte
echo "[+] Generando reporte..."
python3 << 'PYTHON'
import json, datetime

results = []
for f in ['01_recon.json', '02_vulnerabilities.json']:
    try:
        with open(f'$OUTPUT_DIR/{f}') as fp:
            for line in fp:
                results.append(json.loads(line))
    except:
        pass

critical = [r for r in results if r.get('severity') == 'critical']
high = [r for r in results if r.get('severity') == 'high']

print(f"Reporte generado: {datetime.datetime.now().isoformat()}")
print(f"Vulnerabilidades críticas: {len(critical)}")
print(f"Vulnerabilidades altas: {len(high)}")
PYTHON

echo "[+] Reporte guardado en: $OUTPUT_DIR"
echo "[+] Próximos pasos:"
echo "    1. Contactar al equipo de seguridad de $COMPANY"
echo "    2. Darles 90 días para corregir antes de publicar"
echo "    3. Documentar toda la comunicación"
SCRIPT

chmod +x /usr/local/bin/responsible-disclosure.sh

Solución de Problemas

Nuclei tarda demasiado en ejecutarse:

# Reducir la concurrencia
nuclei -u https://tudominio.com -c 10 -rate-limit 10

# Filtrar solo las plantillas más relevantes
nuclei -u https://tudominio.com \
  -t cves/2024/ \
  -severity critical

# Ver el progreso en tiempo real
nuclei -u https://tudominio.com -verbose

Demasiados falsos positivos:

# Ver la plantilla que genera el falso positivo
nuclei -u https://tudominio.com -t ruta/plantilla.yaml -debug

# Excluir plantillas problemáticas
nuclei -u https://tudominio.com -exclude-templates plantilla-problemática

# Actualizar plantillas (muchos FP se corrigen en versiones nuevas)
nuclei -update-templates

Error de conexión o timeout:

# Aumentar el timeout
nuclei -u https://tudominio.com -timeout 30

# Usar un proxy para debug
nuclei -u https://tudominio.com -proxy http://localhost:8080

# Reducir la tasa de peticiones
nuclei -u https://tudominio.com -rate-limit 2

Conclusión

Nuclei transforma el proceso de security testing en algo repetible, automatizable y escalable gracias a su sistema de plantillas YAML. La clave para aprovechar al máximo esta herramienta está en mantener las plantillas actualizadas, crear plantillas personalizadas para las tecnologías específicas de tu stack y integrarlo en los pipelines CI/CD para detectar vulnerabilidades antes de que lleguen a producción. Recuerda siempre obtener autorización explícita antes de escanear cualquier sistema que no sea de tu propiedad.