Neutron, notre moteur d’IA, a obtenu un score de 97,1 % sur le benchmark CyberGym de l’UC Berkeley. En savoir plus

Analyse approfondie

Analyse approfondie

Man-in-the-Middle RDP dans FreeRDP, corrigé dans 3.32.2 (CVE-2026-121392)

Avant 3.32.2, deux contrôles d'identité artisanaux de FreeRDP laissent un man-in-the-middle muni d'une AC de confiance intercepter le trafic RDP. Mettez à jour.

TL;DR

  • Le contrôle d'identité TLS côté client de FreeRDP accepte un certificat dont le Common Name correspond alors que ses Subject Alternative Names ne correspondent pas. Il compare aussi des cibles IP littérales à des noms DNS. Un man-in-the-middle détenant un certificat d'une AC de confiance pour le client peut intercepter les sessions RDP.
  • Toutes les versions de FreeRDP antérieures à 3.32.2 sont concernées, selon l'enregistrement CVE. L'avis de juillet 2026 qui décrivait ces cas annonçait un correctif dans 3.29.0 qui n'a jamais couvert deux de ses trois cas.
  • L'enregistrement CVE de VulnCheck note la faille 9,1 Critical en CVSS v4.0 et 7,4 High en CVSS v3.1. Aucune exploitation n'est connue, et le CVE ne figure pas au catalogue Known Exploited Vulnerabilities (KEV) de la CISA au 4 novembre 2026.
  • Passez à FreeRDP 3.32.2 ou ultérieur maintenant. Aucune solution de contournement par configuration n'est documentée ; voir « Comment corriger ? » pour les produits qui embarquent FreeRDP.

Suis-je concerné ?

Vous êtes exposé lorsque toutes ces conditions sont réunies :

  • Vous exécutez un client fondé sur FreeRDP, ou un produit embarquant FreeRDP, dans une version antérieure à 3.32.2. L'enregistrement CVE marque comme concernée toute version depuis la première.
  • Un attaquant peut intercepter ou rediriger la connexion TCP RDP et présenter un certificat remontant à une AC déjà approuvée par le client. L'avis nomme les scénarios : une AC publique qui émet mal, une AC privée compromise ou malveillante, ou une autre anomalie de chaîne de confiance.
  • Le client vérifie les certificats de serveur. La divulgation d'origine a reproduit la faille avec AutoAcceptCertificate = FALSE, AutoDenyCertificate = TRUE et AuthenticationLevel = 2.

Un attaquant qui ne peut pas obtenir de certificat approuvé ne profite pas de cette faille. Le défaut affaiblit la vérification d'identité du serveur dans les scénarios d'AC de confiance ; il ne crée pas la confiance.

Version Concernée Version corrigée
3.32.1 et toute version antérieure Oui, dans le contrôle d'identité par défaut 3.32.2, publiée le 2026-10-12
3.32.2 et ultérieures, y compris 3.33.0 Non Continuer à mettre à jour

3.32.2 et 3.33.0 comportent un défaut connu dans le nouveau contrôle d'IP, et il échoue en mode fermé : il rejette des correspondances valides au lieu d'accepter de mauvaises (voir « Pourquoi le correctif fonctionne-t-il ? »).

Vérifiez ce que vous exécutez :

# The FreeRDP 3 client front-ends all print the version
xfreerdp3 --version

# Debian-family package installs
dpkg -l | grep freerdp

# Library copies, including those bundled inside other products
ldconfig -p | grep libfreerdp

Un produit qui embarque FreeRDP attend sa propre mise à jour ; la version indiquée par le produit est celle à confronter à l'avis.

Comment corriger ?

  1. Passez à FreeRDP 3.32.2 ou ultérieur. Les commits de correctif sont arrivés dans 3.32.2, publiée le 12 octobre 2026, et chaque version ultérieure les embarque.
  2. Mettez à jour les produits qui embarquent FreeRDP quand leur éditeur publie la bibliothèque corrigée. La plage concernée de l'enregistrement CVE commence à la première version, donc les copies embarquées plus anciennes sont dans le champ.
  3. Considérez une session comme compromise si elle a pu transiter par un intercepteur détenant un certificat approuvé par le client. Un tel attaquant voit le contenu de l'écran, les frappes et le presse-papiers et peut injecter des entrées : changez chaque identifiant utilisé dans cette session et examinez ce qui y a été fait. La faille ne donne pas à l'attaquant cette position réseau ; elle permet à un attaquant qui la détient déjà d'agir dans la session.

Aucune solution de contournement par configuration n'est documentée. L'avis de suivi qui a trouvé le correctif incomplet ne propose aucune atténuation. Son correctif suggéré est ce que 3.32.2 implémente : le Common Name ne compte que si aucun SAN DNS n'existe, et les cibles IP ne correspondent qu'aux entrées SAN iPAddress. FreeRDP a écrit cette logique lui-même au lieu d'appeler les fonctions OpenSSL X509_check_host() et X509_check_ip_asc(), qui appliquent les mêmes règles selon l'avis.

Quelle est la cause racine ?

FreeRDP réalise ses propres comparaisons de chaînes Common Name et SAN DNS au lieu d'utiliser les API de validation d'identité d'OpenSSL. Le bloc vulnérable, libfreerdp/crypto/tls.c lignes 1859 à 1879 au tag 3.32.1 :

/* compare against common name */

if (common_name)
{
    if (tls_match_hostname(common_name, common_name_length, hostname))
        hostname_match = TRUE;
}

/* compare against alternative names */

if (dns_names)
{
    for (size_t index = 0; index < dns_names_count; index++)
    {
        if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
        {
            hostname_match = TRUE;
            break;
        }
    }
}

Deux propriétés de ce bloc cassent la vérification d'identité du serveur :

  • Le contrôle Common Name et le contrôle SAN DNS forment un OU inconditionnel. La section 6.4.4 de la RFC 6125 exige l'inverse : dès qu'un certificat porte une entrée SAN dNSName, le Common Name est sans objet. Un certificat avec CN=rdp01.corp.example et une liste SAN sans correspondance comme DNS:files.corp.example passe quand même pour une connexion à rdp01.corp.example.
  • x509_utils_get_dns_names() ne demande que les entrées GEN_DNS. Le code ne lit nulle part les entrées SAN iPAddress. Quand la cible RDP est un IP littéral, FreeRDP compare donc l'IP comme une simple chaîne au CN et aux entrées SAN DNS.

Un avis de juillet 2026, GHSA-43hh-p3vw-hfx3, documentait trois faiblesses de contrôle d'identité et indiquait que la version 3.29.0 les corrigeait. Son jeu de correctifs n'a fermé que le premier cas, une troncature par NUL incorporé. Les cas du Common Name et de l'IP littérale sont restés identiques octet pour octet depuis le tag 3.29.0, et GHSA-jq25-3374-4262 a documenté cet écart résiduel en octobre 2026.

Comment la faille est-elle exploitée ?

  1. L'attaquant obtient une position pour intercepter ou rediriger la connexion RDP de la victime. Il lui faut aussi un certificat remontant à une AC approuvée par le client, dont le Common Name est le nom d'hôte cible ou dont un SAN DNS contient l'IP cible sous forme de texte.
  2. Le client FreeRDP de la victime se connecte et exécute tls_verify_certificate() sur le certificat de l'attaquant. Les contrôles de chaîne et de validité passent, car le certificat est réellement émis par une AC de confiance.
  3. La branche Common Name met hostname_match = TRUE bien que les entrées SAN ne correspondent pas, ou la cible IP littérale correspond à une chaîne SAN DNS. Le client accepte le certificat comme identifiant le serveur.
  4. L'extrémité de l'attaquant transporte alors la session RDP : contenu d'écran, frappes, presse-papiers et injection d'entrées, dans la description d'impact de l'avis de suivi.

Aucune preuve de concept publique n'existe au-delà des notes de reproduction des deux avis. L'avis d'origine a reproduit les trois cas dans le chemin de handshake TLS de FreeRDP, avec une AC de test locale installée dans un magasin de certificats FreeRDP isolé. Le suivi a appelé directement tls_verify_certificate() non modifiée sur des certificats à chaîne vérifiée, sans handshake réseau complet.

Comment l'attaque se déroule-t-elle ?

Un man-in-the-middle muni d'un certificat approuvé sert la session RDP, et le contrôle d'identité artisanal accepte le certificat sans correspondance.

flowchart LR A["Le man-in-the-middle détient un
certificat d'AC de confiance"] --> B["La victime se connecte au
serveur RDP"] B --> C["tls_verify_certificate s'exécute sur
le certificat de l'attaquant"] C --> D["Le CN correspond, les entrées SAN
non : OU inconditionnel"] D --> E["Aucune entrée SAN iPAddress
n'est jamais lue pour les cibles IP"] E --> F["Le client accepte
l'identité de l'attaquant"] F --> G["Trafic de session : écran,
frappes, presse-papiers"]

Que peut faire un attaquant ?

L'attaquant intercepte la session RDP en entier : contenu d'écran, frappes, presse-papiers et injection d'entrées, selon la déclaration d'impact de l'avis de suivi. Aucun des deux avis ne revendique d'exécution de code ni d'extraction directe d'identifiants, et l'avis d'origine ne revendique pas non plus de corruption de mémoire.

L'attaque exige d'abord la position réseau et le certificat approuvé. Un certificat dont l'émetteur n'est pas approuvé par le client échoue au contrôle de chaîne avant la comparaison d'identité. Un client qui épingle ou vérifie manuellement les certificats indépendamment de ce chemin est hors du scénario décrit.

Pourquoi le correctif fonctionne-t-il ?

Deux commits de 3.32.2 remplacent la comparaison artisanale pour les deux cas. Le commit 1a23b21c37, « do not check common name if there are DNS SAN », place la comparaison Common Name derrière un else if :

        common_name = freerdp_certificate_get_common_name(cert, &common_name_length);
        dns_names = freerdp_certificate_get_dns_names(cert, &dns_names_count, &dns_names_lengths);
-
-       /* compare against common name */
-
-       if (common_name)
-       {
-           if (tls_match_hostname(common_name, common_name_length, hostname))
-               hostname_match = TRUE;
-       }
-
        /* compare against alternative names */
-
        if (dns_names)
        {
            for (size_t index = 0; index < dns_names_count; index++)
@@
            }
        }
+       /* compare against common name */
+       else if (common_name)
+       {
+           if (tls_match_hostname(common_name, common_name_length, hostname))
+               hostname_match = TRUE;
+       }

Le Common Name n'est désormais consulté que lorsque le certificat n'a aucune entrée SAN DNS, ce qui est la règle de la section 6.4.4 de la RFC 6125.

Le commit 350539ec9a, « add IP SAN checks », ajoute un chemin d'extraction des iPAddress. Quand la cible de connexion s'analyse comme une IP, la boucle la compare aux entrées SAN iPAddress du certificat via une comparaison binaire, sans jamais retomber sur la comparaison de chaînes DNS.

Le correctif est complet pour les deux cas signalés. Le bloc que réécrivent les deux commits contient les seuls appels à tls_match_hostname() du projet. Le troisième cas de l'avis d'origine, la troncature par NUL incorporé, était déjà corrigé dans 3.29.0.

Un défaut subsiste dans le nouveau chemin IP, et il échoue en mode fermé. Dans 3.32.2 et 3.33.0, la fonction utils_compare_ip_strings() rejette toute adresse valide, car elle teste la mauvaise valeur de retour de inet_pton(). Une cible IP littérale ne correspond donc jamais à une entrée SAN iPAddress, et le client se rabat sur sa vérification known-hosts ou sur l'invite. Le commit f5e8a54fb2 a corrigé ce test le 3 novembre 2026, après la publication de 3.33.0.

Comment savoir si j'ai été compromis ?

Aucun indicateur n'est publié, et les avis ne rapportent aucune exploitation. Une interception réussie ressemble à une session TLS ordinaire pour le client.

Le client ne garde aucune trace de l'attaque. Quand la chaîne est approuvée et que le nom correspond, tls_verify_certificate() accepte le certificat sans lire ni mettre à jour le magasin known-hosts de FreeRDP : le certificat de l'attaquant n'y laisse aucune entrée. Les journaux de connexion RDP de vos serveurs sont une meilleure piste : une session depuis une adresse source inattendue mérite une vérification, mais ne prouve pas une interception.

Chronologie

  • 2026-07-15 : GHSA-43hh-p3vw-hfx3 est publié, documentant trois faiblesses de contrôle d'identité et indiquant que 3.29.0 les corrigeait.
  • 2026-10-07 : Les deux commits de correctif pour les cas résiduels sont rédigés par Armin Novak.
  • 2026-10-12 : FreeRDP 3.32.2 est publiée avec les correctifs, au sein d'une version de durcissement plus large.
  • 2026-10-19 : GHSA-jq25-3374-4262 est publié, documentant que 2 des 3 cas n'avaient jamais été corrigés dans 3.29.0.
  • 2026-11-03 : CVE-2026-121392 est publié par VulnCheck avec le score CVSS v4.0 de 9,1 Critical.

L'avis qui annonçait un correctif dans 3.29.0 a précédé de 84 jours le vrai correctif, et l'enregistrement CVE a suivi la publication de 22 jours.
Figure 1 : de l'avis de juillet annonçant un correctif à l'enregistrement CVE de novembre. Source : avis et versions FreeRDP et enregistrement CVE VulnCheck, consultés le 4 novembre 2026

L'avis disait que 3.29.0 fermait ces cas. Les commits de correctif sont arrivés 84 jours après cet avis, et la version qui les a livrés 89 jours après.

FAQ

Pourquoi la faille est-elle notée à la fois Critical et High ?

Les deux notes viennent de deux versions de CVSS appliquées aux mêmes faits. VulnCheck, l'autorité d'attribution des CVE (CNA) qui a publié l'enregistrement, la note 9,1 Critical en CVSS v4.0, CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N. VulnCheck et l'avis de FreeRDP lui-même la notent tous deux 7,4 High en CVSS v3.1, CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N.

La faille touche-t-elle le serveur ou le proxy FreeRDP ?

La faille est dans la vérification d'identité du serveur côté client, dans tls_verify_certificate(). Les notes de version de 3.32.2 listent 44 autres avis dans le même lot, qui durcissent le code contre des messages malveillants de clients et de serveurs.

L'avis d'origine était-il erroné ?

Son champ des versions corrigées indiquait 3.29.0. Le suivi a montré que le jeu de correctifs de 3.29.0 ne fermait que le cas du NUL incorporé. Les deux autres cas étaient identiques octet pour octet depuis ce tag. Le champ était inexact pour 2 des 3 cas documentés.

Qui a signalé ces failles ?

L'avis d'origine des trois cas a été signalé par Bin Luo, de l'Université des sciences et technologies électroniques de Chine (UESTC), utilisateur GitHub 1121984919, selon l'avis. Le rapport de suivi documentant le correctif incomplet ne nomme pas de rapporteur. Il divulgue que Claude a été utilisé comme outil sous la direction du rapporteur. Celui-ci a revérifié chaque commit et ligne cités avant la soumission.

Passer à 3.33.0 corrige-t-il aussi ?

Oui. Les correctifs sont arrivés dans 3.32.2, et 3.33.0, publiée le 2 novembre 2026, les embarque. La version 3.32.2 est le minimum.

Repérez les copies de FreeRDP de votre patrimoine avant qu'un intercepteur ne le fasse

Toute version de FreeRDP antérieure à 3.32.2 est dans la plage concernée, y compris les copies embarquées dans des produits. L'analyse SCA et SBOM d'Ostorlab inventorie les dépendances de vos dépôts et images, pour savoir quels composants et produits embarquent un FreeRDP concerné.

Références

  • CVE-2026-121392, enregistrement CVE de VulnCheck avec les deux vecteurs CVSS : https://www.cve.org/CVERecord?id=CVE-2026-121392 (consulté le 4 novembre 2026)
  • Avis VulnCheck, « FreeRDP before 3.32.2 Certificate Identity Validation Bypass via tls_verify_certificate » : https://www.vulncheck.com/advisories/freerdp-before-3.32.2-certificate-identity-validation-bypass-via-tls-verify-certificate (consulté le 4 novembre 2026)
  • GHSA-jq25-3374-4262, avis FreeRDP, « Incomplete fix for GHSA-43hh-p3vw-hfx3 » : https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-jq25-3374-4262 (consulté le 4 novembre 2026)
  • GHSA-43hh-p3vw-hfx3, avis FreeRDP, « TLS certificate identity validation accepts malformed and non-authoritative identities » : https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-43hh-p3vw-hfx3 (consulté le 4 novembre 2026)
  • Commit de correctif 1a23b21c37, « [crypto,tls] do not check common name if there are DNS SAN » : https://github.com/FreeRDP/FreeRDP/commit/1a23b21c37 (consulté le 4 novembre 2026)
  • Commit de correctif 350539ec9a, « [crypto,tls] add IP SAN checks » : https://github.com/FreeRDP/FreeRDP/commit/350539ec9a (consulté le 4 novembre 2026)
  • Commit de suivi f5e8a54fb2, « [core,utils] fix return check for inet_pton » : https://github.com/FreeRDP/FreeRDP/commit/f5e8a54fb2 (consulté le 4 novembre 2026)
  • Notes de version de FreeRDP 3.32.2 : https://github.com/FreeRDP/FreeRDP/releases/tag/3.32.2 (consultées le 4 novembre 2026)
  • Source vulnérable, libfreerdp/crypto/tls.c au tag 3.32.1 : https://raw.githubusercontent.com/FreeRDP/FreeRDP/3.32.1/libfreerdp/crypto/tls.c (consultée le 4 novembre 2026)
  • Catalogue Known Exploited Vulnerabilities de la CISA, flux JSON, recherche de CVE-2026-121392 : https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (consulté le 4 novembre 2026)