Skip to content
KitploitKITPLOIT
OutilsBlog
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
Outils/GitHubGitHub/eaea0001/servu-cve-2026-28318-poc
Criminalistique MémoireAnalyse des VulnérabilitésExploitationTests d'IntrusionAnalyse de Binaires
GitHubeaea0001/servu-cve-2026-28318-poc

servu-cve-2026-28318-poc

SolarWinds Serv-U CVE-2026-28318 : crash non authentifié de Content-Encoding: deflate. Analyse de la cause racine (invalid free of an interior pointer -> heap corruption) + DoS-only PoC. Corrigé dans la version 15.5.4 Hotfix 1.

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 →
Partager
Voir le dépôt
13il y a 3 moisPas encore vérifié

CVE-2026-28318 — SolarWinds Serv-U "Content-Encoding: deflate" crash sans authentification

Analyse de la cause racine + preuve de concept DoS. L'avis public classe cela comme un déni de service / consommation de ressources non contrôlée sans authentification. L'analyse binaire montre que le défaut sous-jacent est memory-safety : un free() invalide d'un pointeur intérieur dans le chemin de décodage deflate HTTP, qui corrompt le tas du processus (STATUS_HEAP_CORRUPTION, 0xC0000374). Il ne s'agit pas d'une bombe de décompression, et le crash est indépendant de la taille décompressée.


⚠️ Avertissement / portée

  • Ceci est une recherche défensive en sécurité pour une vulnérabilité déjà corrigée et divulguée publiquement (correctif livré le 2026-06-04 dans Serv-U 15.5.4 Hotfix 1 ; répertorié dans CISA KEV).
  • La PoC ici ne fait que crasher une instance Serv-U que vous possédez ou êtes explicitement autorisé à tester. Elle est DoS uniquement — aucune exécution de code à distance n'est incluse ou démontrée (voir Sévérité).
  • Utilisez-la pour valider l'état du correctif et la détection sur vos propres systèmes. Ne l'utilisez pas contre des systèmes que vous ne contrôlez pas. Vous êtes responsable du respect de la loi applicable.

Affecté / Corrigé

N'affecte que l'écouteur HTTP/HTTPS (le chemin web/administration). Les protocoles FTP/FTPS/SFTP ne sont pas sur ce chemin de code.


TL;DR

Toute requête HTTP portant Content-Encoding: deflate avec un corps deflate valide fait crasher le service. Le gestionnaire décompresse le corps, puis libère le pointeur vers le corps compressé et échange avec le tampon décompressé — mais ce pointeur est un pointeur intérieur dans le tampon de réception HTTP (il pointe vers le corps, juste après le \r\n\r\n), pas une base d'allocation du tas. Appeler free() sur un pointeur non-base et non aligné corrompt le tas et le processus meurt.

Parce que le bogue réside dans la façon dont le pointeur du corps est libéré — et non dans la quantité de données produites — même un corps compressé d'environ 25 octets (qui se décompresse en quelques Ko) le crashe de manière fiable. La mémoire utilisée n'augmente pas ; ce n'est pas une "bombe zip/deflate."


Cause racine

La routine de décodage deflate se trouve dans RhinoNET.dll (la bibliothèque réseau de Serv-U) et est atteinte depuis le chemin de réception HTTP (ProcessReceive) une fois que l'analyseur d'en-tête a défini le drapeau "deflate" lors de la détection de Content-Encoding: deflate.

Simplifiée, la routine est appelée comme decode(this, &bodyPtr, &bodyLen) et fait :

root@kitploit:~
1. inflate bodyPtr[0..bodyLen]  -> grossit un tampon accumulateur `acc`   (zlib standard, borné, correct)
2. free(*bodyPtr)                <-- *bodyPtr est un pointeur INTÉRIEUR dans le tampon de réception
3. *bodyPtr = acc                // remplace le corps compressé par le tampon décompressé
4. *bodyLen = total

L'étape 2 est le bogue. *bodyPtr n'est pas un bloc alloué indépendamment : il pointe vers le corps de la requête à l'intérieur du tampon de réception HTTP unique, c'est-à-dire receive_buffer + header_length. Libérer un pointeur intérieur (et non aligné sur 16 octets) amène l'allocateur à analyser une région influencée par l'attaquant comme un en-tête de chunk du tas → corruption des métadonnées du tas → 0xC0000374.

Ce qui a été éliminé (pour ne pas vous tromper)

Les deux hypothèses "évidentes" sont fausses, vérifiées à l'exécution :

  • Pas un débordement de décompression/inflate. Le décompresseur est le zlib1.dll!inflate standard et respecte avail_out à chaque appel (observé sur plus de 100 chunks ; aucune écriture hors limites).
  • Pas un débordement d'accumulateur. Le tampon de sortie croissant est alloué comme prev_total + produced + 1 à chaque tour et écrit exactement cette quantité — serré, aucun débordement.

La corruption est uniquement due au free() invalide de l'étape 2.


Preuves

Capturées à l'exécution (Frida) contre Serv-U 15.5.4.108 lors de l'envoi d'une requête Content-Encoding: deflate dont le corps se décompresse en "A" * 8192 :

  • Le pointeur libéré est …ce — mod 16 == 14. Les bases d'allocation du tas sont alignées sur 16 octets, donc ce n'est pas une base d'allocation ; c'est un pointeur intérieur.
  • Les 48 octets avant le pointeur libéré sont la fin de l'en-tête HTTP, se terminant par \r\n\r\n :
    root@kitploit:~
    …tream\r\nContent-Length: 26\r\nConnection: close\r\n\r\n
    
  • Les octets à l'adresse du pointeur libéré sont un flux deflate brut (ed c1 01 0d 00 …).
  • Signature du crash : module fautif ntdll.dll, exception 0xC0000374 (STATUS_HEAP_CORRUPTION), avec l'appel provenant du free dans le gestionnaire deflate de RhinoNET.dll. La dernière opération de tas avant le crash est exactement ce free(bodyPtr).
  • Indépendance de la taille : un corps qui se décompresse en seulement ~4 Ko (compressé ≈ quelques dizaines d'octets) crashe identiquement ; la mémoire de travail n'augmente pas.

Sévérité

  • Confirmé : crash distant fiable sans authentification du service Serv-U (DoS). Le service peut redémarrer automatiquement, mais des requêtes répétées le maintiennent hors service et peuvent épuiser la récupération du service Windows.
  • Au-delà du DoS — non prouvé. L' "en-tête de chunk" libéré chevauche des octets d'en-tête HTTP contrôlés par l'attaquant, ce qui est en principe une primitive plus forte qu'un simple DoS. Cependant, sur Windows moderne (Segment Heap), le free invalide échoue rapidement (0xC0000374) dans nos tests, et nous n'avons pas obtenu d'exécution de code. Considérez cela comme un DoS par corruption du tas sans authentification avec une cause racine de sécurité mémoire ; ne supposez pas d'exécution de code à distance.

Reproduire

Nécessite Python 3 (bibliothèque standard uniquement). Pointez-le vers un écouteur HTTP Serv-U que vous êtes autorisé à tester. Sous Windows, il utilise un appel Get-NetTCPConnection pour lire le PID de l'écouteur et le journal des événements d'application pour confirmer le crash de corruption du tas.

root@kitploit:~
python poc_verify.py                       # par défaut 127.0.0.1:80, petit paquet, 1 tir
python poc_verify.py --host <ip> --port 80
python poc_verify.py --big                 # corps se décompresse en 8192 octets
python poc_verify.py --shots 3
python poc_verify.py --no-events           # sauter la vérification du journal des événements (aucun privilège nécessaire)

La PoC construit une requête minimale :

root@kitploit:~
POST / HTTP/1.1
Host: <cible>
Content-Encoding: deflate
Content-Type: application/octet-stream
Content-Length: <n>
Connection: close

<corps deflate brut — même quelques dizaines d'octets suffisent>

Elle signale PASS si le service a crashé (PID de l'écouteur changé / événement 0xC0000374 apparu) et FAIL s'il a survécu (déjà corrigé, non affecté, ou le corps n'a pas été traité comme deflate).


Atténuation

  1. Appliquez Serv-U 15.5.4 Hotfix 1 (ou ultérieur).
  2. En attendant : devant Serv-U, supprimez ou rejetez le Content-Encoding entrant sur l'écouteur HTTP/HTTPS, par exemple sur un proxy inverse :
    root@kitploit:~
    if ($http_content_encoding) { return 400; }
    
  3. Restreignez l'exposition réseau du port web/administration de Serv-U.

Méthodologie (comment cela a été analysé)

  • Statique : désassemblage PE paramétré de RhinoNET.dll / Serv-U.exe (base de l'image 0x180000000) pour cartographier le chemin réception → analyse d'en-tête → décodage deflate et localiser le free erroné.
  • Dynamique : instrumentation Frida du service en direct — accrochage du décompresseur pour prouver que zlib respecte avail_out, traçage de chaque alloc/free/memcpy de l'appel de décodage vers le disque, et un gestionnaire d'exception de processus pour capturer l'instruction fautive et la pile 0xC0000374 au moment de la corruption. Le free du pointeur intérieur a ensuite été confirmé en vidant les octets autour du pointeur libéré (queue d'en-tête HTTP + corps deflate brut, non aligné sur 16 octets).

Les décalages référencés dans l'analyse sont spécifiques à la build 15.5.4.108 et différeront selon les builds.


Références

  • SolarWinds — Notes de version de Serv-U 15.5.4 Hotfix 1
  • NVD — CVE-2026-28318
  • Catalogue CISA KEV — CVE-2026-28318

Publié en tant que recherche défensive après disponibilité du correctif du fournisseur. La PoC est uniquement DoS et destinée à des tests autorisés.

Télécharger l’outil
ProduitSolarWinds Serv-U (FTP / MFT / File Server)
Vulnérable15.5.4 et versions antérieures dans cette branche sans le Hotfix 1 (analyse effectuée sur la build 15.5.4.108)
CorrigéServ-U 15.5.4 Hotfix 1 (publié le 2026-06-04)
VecteurSans authentification, réseau (port HTTP/HTTPS de gestion/web)
Classe publiqueCWE-400 Uncontrolled Resource Consumption · DoS · CVSS 7.5 · CISA KEV
Classe réelleCWE-763 Release of Invalid Pointer / CWE-590 Free of Memory not on the Heap → corruption du tas