Les mises à jour de sécurité publiées par Microsoft le 11 avril 2023 corrigeaient plus de 90 vulnérabilités individuelles. Il convient de noter en particulier la vulnérabilité CVE-2023-21554, baptisé QueueJumper, une vulnérabilité d’exécution de code à distance affectant le service Microsoft Message Queueing (MSMQ). MSMQ est un composant Windows facultatif qui permet aux applications d’échanger des messages via des files d’attente accessibles à la fois localement et à distance. Cette analyse a été réalisée en collaboration avec les équipes Randori et X-Force Adversary Services, par Valentina Palmiotti, Fabius Watson et Aaron Portnoy.
Les caractéristiques suivantes de la vulnérabilité CVE-2023-21554 ont initialement attiré l'attention :
Restez au fait des tendances les plus étonnantes du secteur dans le domaine de l’IA, de l’automatisation, des données et bien d’autres avec la newsletter Think. Consultez la Déclaration de confidentialité d’IBM.
Afin de déterminer comment détecter la présence de MSMQ, un système de test a été configuré avec le composant dans un environnement de laboratoire. Lors de la connexion au point de terminaison MSMQ sur le port 1801, le serveur n'a répondu avec aucune donnée. On peut supposer que le serveur ne répondra pas sans avoir reçu de données correctement entraînées. Afin de comprendre comment mener une conversation avec le point de terminaison, il a été nécessaire d'examiner plus en détail le code sous-jacent.
L'avis ne précise pas clairement quel fichier binaire a été corrigé. La première étape pour identifier le code modifié consistait à télécharger le fichier de mise à jour. Pour ce faire, il a fallu rechercher KB5025224 dans le catalogue Microsoft Update.
Résultats de recherche dans le catalogue Microsoft Update pour KB5025224
Plus précisément, le fichier de mise à jour cumulative
windows10.0-kb5025224-x64_3522b1b562ed44bc949541dd1c7d08e1e967d925.msu
La version pour Windows 11 pour systèmes x86 a été récupérée.
L'extracteur 7-Zip a été utilisé pour décompresser le contenu du fichier MSU et des fichiers CAB qu'il contenait. La recherche de la chaîne « msmq » dans tous les fichiers des dossiers résultants a permis de trouver le fichier d'index du conteneur,
Windows11.0-KB5025239-x64/express.psf.cix.xml,
qui comprenait l’entrée suivante :
<File id="21296" name="amd64_microsoft-windows-msmq-queuemanager-core_31bf3856ad364e35_10.0.22621.1555_none_5f975f8fdb349517\f\mqqm.dll" length="34811" time="133245266510000000" attr="128">
Cette entrée référence
Pour identifier les changements apportés entre les versions corrigées et non corrigées du fichier MQQM.dll1.00
Résultats BinDiff entre les fichiers MQQM.dll corrigés et non corrigés
En analysant ces fonctions à l'aide de Hex-Rays Decompiler, des symboles pour la version corrigée contenant des noms de fonction verbeux semblent faire référence aux identifiants de vulnérabilité du Microsoft Security Research Center (MSRC) :
Symboles des indicateurs de fonctionnalité dans MQQM.dll
Après un examen plus approfondi, les symboles contenant les numéros de dossier du CSEM correspondent à des drapeaux defonctionnalité pour la correction des vulnérabilités. Les drapeaux de fonctionnalité sont un composant de Windows qui permet d'activer diverses fonctionnalités et expériences. Ici, la "fonctionnalité" découverte est en fait un correctif pour une vulnérabilité. Si la fonctionnalité est activée, le chemin de code sécurisé et corrigé est exécuté. Dans le cas contraire, le chemin de code original non corrigé est exécuté.
Extrait de code décompilé illustrant l'indicateur de fonctionnalité pour la correction de vulnérabilité
Une vérification des indicateurs de fonctionnalité était présente pour chacune des vulnérabilités qui composaient la CVE-2023-21554 dans les composants utilisateur et noyau. L'analyse des binaires restants contenus dans le package de mise à jour de sécurité a révélé que des indicateurs de fonctionnalité avaient également été introduits pour la plupart ou la totalité des vulnérabilités corrigées lors du Patch Tuesday d'avril 2023.
Le référencement croisé de ces indicateurs nous a permis d'identifier rapidement les emplacements de code corrigés. En particulier, les changements au sein de qui concernent les indicateurs d’ixesMSRC76146_MSMQ_OOBRWF
La vérification de cet indicateur de fonctionnalité se produit huit fois dans la fonction. Un exemple de ce type de vérification est présentée ci-dessous :
Extrait de code décompilé illustrant la correction de la vulnérabilité
Dans l’extrait de code décompilé montré ci-dessus, le chemin de code corrigé obtient le pointeur vers la section suivante du message MSMQ via un appel à
Extrait de décompilation de la fonction GetNextSectionPtrSafe
Après avoir examiné toutes les occurrences de cet indicateur de fonctionnalité et d'autres, il a été déterminé que la vulnérabilité CVE-2023-21554 comprend plusieurs bugs qui ne vérifient pas suffisamment la taille de divers types de sections de messages MSMQ. Ces vulnérabilités permettent d'incrémenter le pointeur vers la fin du message MSMQ d'un décalage arbitraire de 32 bits en dehors des limites de la mémoire tampon initialement allouée.
Après le traitement du paquet, la dernière étape de
Vérification de l'accès à la mémoire hors limites pour la fin du message
Lors de l’évaluation de l’exploitabilité des vulnérabilités, des vulnérabilités de noyau supplémentaires ont été identifiées dans le pilote de noyau correspondant pour le service MSMQ,. Les vulnérabilités ont de nouveau été indiquées par des symboles d’indicateurs de fonctionnalité, qui font également référence au cas 76146 du MSRC, tel qu'il a été observé dans .
Symboles de fonctionnalité dans mqac.sys
L’analyse de l’indicateur de fonctionnalité
Pour effectuer les opérations associées, le composant du noyau analyse différentes sections du tampon de paquets MSMQ. Deux exemples de ce type sont illustrés ci-dessous :
Extrait de code décompilé montrant la fonctionnalité pour les correctifs des vulnérabilités dans le pilote mqac.sys
Comme le montre l'extrait de code décompilé ci-dessus, si l’indicateur de fonctionnalité est activé, les fonctions « sécurisées »
La majorité du code lié à l’analyse du protocole se trouve dans la bibliothèque qui est chargée par le processusmqsvc.exe, une requête MSMQ valide doit être envoyée par le client. La spécification et le protocole des messages MSMQ sont vastes et complexes. Au départ, un code public a été trouvé pour l’analyse des serveurs MSMQ dans un GitHub qui a servi de base à une exploration plus approfondie du traitement des paquets. De plus, la documentation Microsoft a été utile pour comprendre le formatdes messages MSMQ.
Le code dans la DLL accepte les données via le port 1801 à l’aide d’un appel à la fonction WSARecv, comme illustré dans la session de débogage ci-dessous :
0:020> bp ws2_32!wsarecv ; g
Point d’arrêt 0 atteint
WS2_32!WSARecv:
00007ffd`651115c0 48895c2408 mov qword ptr [rsp+8],rbx ss:000000aa`f07fef30=0000000000000006
0:019> k
# Child-SP RetAddr Call Site
00 000000aa`f07fef28 00007ffd`57ba9cb0 WS2_32!WSARecv
01 000000aa`f07fef30 00007ffd`57b9683d
MQQM!NoReceivePartialBuffer+0x38
02 000000aa`f07fefb0 00007ffd`57b2078e MQQM!CWinsockConnection::ReceivePartialBuffer+0x7d
03 000000aa`f07ff010 00007ffd`57b25b28
MQQM!CSockTransport::BeginReceive+0xe6
04 000000aa`f07ff060 00007ffd`57b2d40b
MQQM!CSockTransport::NewSession+0x194
05 000000aa`f07ff3f0 00007ffd`57b2d367 MQQM!CSessionMgr::AcceptSockSession+0x6f
06 000000aa`f07ff430 00007ffd`645e26bd MQQM!AcceptIPThread+0x6a7
07 000000aa`f07ff7d0 00007ffd`6650a9f8
KERNEL32!BaseThreadInitThunk+0x1d
08 000000aa`f07ff800 00000000`00000000 ntdll!RtlUserThreadStart+0x28
0:019> r @$t0=@rdx
0:019> pt
WS2_32!WSARecv+0x19f:
00007ffd`6511175f c3 ret
0:019> dc poi(@$t0+8) LC
000001b5`880ff490 62f06110 524f494c 00000070 5a5a5a5a .a.bLIORp…ZZZZ
000001b5`880ff4a0 0073006e 00610074 0063006e 00200065 n.s.t.a.n.c.e.
000001b5`880ff4b0 00440049 00000000 00000000 00000000 I.D………….
0:019> ba r1 poi(@$t0+8) ; g
Point d’arrêt 1 atteint
MQQM!CBaseHeader::SectionIsValid+0x154:
00007ffd`57b53450 7462 je
MQQM!CBaseHeader::SectionIsValid+0x1b8 (00007ffd`57b534b4) [br=1]
La fonction est chargée d’analyser le début d’un nouveau message, qui commence par une structure BaseHeader de la forme :
Structure de l'objet BaseHeader
Les champs de messages entrants sont validés par
Code de désassemblage pour SectionIsValid dans MQQM.dll
Après la validation initiale, la majeure partie de l’analyse du protocole s’effectue dans la fonction de construction
Décompilation démontrant une vulnérabilité dans le traitement d’EodHeader
La décompilation ci-dessus montre le chemin corrigé appelant la fonction nommée
La structure d’un
Démontage et calcul de la taille totale de la section EodHeader
Dans le désassemblage ci-dessus, le pointeur au début de
Session WinDbg indiquant une violation d'accès lors de l'écriture à la fin d'un message MSMQ mal formé
Afin d'évaluer la gravité de l'écriture hors limites obtenue par les vulnérabilités, nous avons d'abord examiné l'allocation et la gestion de la mémoire sous-jacente.
Avant qu'un paquet de messagesMSMQ. Cette fonction appelle le pilote du noyau viaNtDeviceIoControl.
Décompilation de la fonction d’allocation de la mémoire tampon de paquets
Le composant du noyau renvoie une mémoire tampon partitionnée à partir de la vue cartographiée d’un fichier sur disque, stocké dans le répertoire
Disposition de la mémoire ProcessHacker du processus MQSVC indiquant que la mémoire tampon des paquets est un mappage de fichier.
L’adresse de la mémoire tampon, ainsi qu’un identifiant de paquet aléatoire, est renvoyée à l’espace utilisateur suite à la demande d’allocation via IOCTL. Le pilote utilise le gérer pour calculer l’adresse du tampon de paquet lors du traitement des requêtes provenant de l’espace utilisateur.
La mémoire de sauvegarde pour les tampons vulnérables se trouve dans un fichier mappé, et donc pas dans la mémoire du processus. De plus, la mémoire affectée ne stocke aucun objet. Le fichier mappé contient uniquement le contenu des messages MSMQ ainsi que les métadonnées stockées dans le
De plus, sans connaissance préalable de la disposition de la mémoire, il n'est pas possible de connaître le positionnement relatif du mappage de fichiers par rapport au tas du processus afin de remplacer les pointeurs d'objets. Par conséquent, afin de pouvoir exécuter du code à distance, nous avons besoin d'une méthode permettant de configurer la mémoire dans une position prévisible.
Après avoir expérimenté l'envoi de messages MSMQ légitimes à la cible, on a découvert qu'il était possible de forcer une nouvelle allocation du tas adjacente à une cartographie de fichier
Disposition de la mémoire du processus MQSVC montrant une nouvelle mémoire allouée à proximité d’un mappage de fichier MQ
Toutefois, il faut pour cela que l’attaquant ait accès à l’envoi de messages à au moins une file d’attente sur la cible, faute de quoi les messages seront rejetés et écrasés et n’occuperont donc pas la mémoire des paquets de manière persistante.
Dans le cadre de l’expérimentation menée, il a été constaté qu’un utilisateur non privilégié pouvait créer une file d’attente ouverte à tous pour envoyer des messages à distance, par défaut. La file d’attente est conservée indéfiniment sur le système. Bien que la plupart des utilisations modernes de MSMQ existent sous forme de composants et d’adaptateurs optionnels, des fournisseurs tels qu’Oracle, Veritas et Xerox proposent des logiciels d’entreprise qui s’appuient sur MSMQ comme dépendance principale. Le scénario de l’attaque n’est donc pas irréaliste.
La vulnérabilité d’accès mémoire hors limites introduit une primitive d’exploitation qui permet à un
client malveillant d’écrire unOnDiskExtensionHeader
allouée pour le paquet.
Lors de l’évaluation d’une vulnérabilité qui permet d’écrire des valeurs dans un décalage, certaines propriétés
doivent être prises en compte :
Dans le cas des vulnérabilités QueueJumper, le décalage du tampon alloué à l’écriture OOB est contrôlable, car il est calculé à l’aide de données contrôlées par le pirate. Le contenu de l’écriture OOB, cependant, a un contrôle limité.
Ici,Address sera écrit. La série d’opérations qui se produisent est la suivante :
0x000000000000000C
est écrite dansAddress0x00000000Address+0x2
0x0000000000000000Address+0x12
0x0000000000000000
est écrite dans Address+0x1A
0x00000094
est écrite Address+0xE
0x0000Address+0x220x0000
est écrite dans Address+0x62
memcpy(Address+0xA6, Source, Source->AddressLength+0x08)
LeSourcememcpy définit une seule adresse de transport d’un type spécifique (par exemple, NetBIOS). La définition est la suivante :
typedef struct _TA_ADDRESS {
USHORT AddressLength;;
USHORT AddressType; Info;
UCHAR Address[1];;
} TA_ADDRESS, *PTA_ADDRESS;
Spécifie le nombre d’octets dans une adresse du type AddressType spécifié.
Spécifie le type d’adresse de transport.
Spécifie un tableau de taille variable contenant l’adresse de transport.
Dans une session de débogage ci-dessous,TA_ADDRESS
rax=0000014e1d110180 rbx=0000014e1d110180 rcx=0000014e1d110184
rdx=0000014e1ce86b10 rsi=0000014e1d110001 rdi=0000000545d7fa50
rip=00007ff843208074 rsp=0000000545d7f940 rbp=0000000545d7f980
r8=000000000000000c r9=0000000000000002 r10=0000000000000000
r11=0000000545d7f938 r12=0000000000000002 r13=0000000000001000
r14=0000014e1ce86b10 r15=0000000000000000
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
MQQM!CQmPacket::CQmPacket+0x89c:
00007ff8`43208074 e8a5780a00 call MQQM!memcpy (00007ff8`432af91e)
0:017> dc rcx
0000014e`1d110184 00010004 00000000 8620a8c0 00000000 ………. …..
Ci-dessus, l’objetTA_ADDRESS, un type de1. En convertissant chaque octet en octet IPv4, on obtient l’adresse , qui correspond à l’adresse source IPv4 du client.
Ce scénario permet l’écriture de données contrôlées par l’attaquant via une adresse source vers un décalage contrôlé à partir de l’allocation de paquets en mémoire. Bien que très restrictif et potentiellement peu pratique, cela pourrait théoriquement être utilisé pour contrôler avec précision les valeurs écrites en mémoire en effectuant plusieurs requêtes à partir d’adresses sources variables à des décalages de paquets dégressifs.
En raison des nombreuses contraintes rencontrées pour parvenir à l'exécution à distance de code à l'insu de l'utilisateur, d'autres scénarios d'attaque, tels que les fuites d'informations, ont été étudiés.
Une attaque envisagée consistait à corrompre le pointeur vers une section spécifique du message afin qu'il pointe vers une mémoire hors limites, puis à récupérer le message pour lire la mémoire adjacente.
Cependant, au début de l'analyse de chaque section, la position de la section actuelle est vérifiée. Il n'est donc pas possible de tromper la logique d'analyse afin qu'elle analyse une section de données hors limites.
Un autre scénario d'attaque possible consiste à écraser l'en-tête OnDiskExtensionHeader d'un autre message afin de tromper le destinataire du message sur l'origine du message reçu. De même, il est possible d'écraser le contenu des messages destinés à des files d'attente auxquelles le pirate n'a pas accès. Pour écraser le contenu spécifique d'un message, le pirate doit disposer d'informations sur le message, telles que sa taille.
Il existe une section facultative nommée SoapHeader qui est susceptible d'accès aux données hors limites, au format suivant :
Format de paquet SoapHeader
Il a été constaté que la mémoire utilisée pour stocker les données des paquets MSMQ n'est pas correctement effacée lorsque la mémoire tampon est vidée. Par conséquent, l'envoi d'un paquet MSMQ dont la taille est inférieure à celle d'un paquet MSMQ précédent entraîne une disposition de la mémoire contenant les données du paquet actuel suivies des données des paquets MSMQ précédemment traités.
On a découvert que le
Le contrôle limité des contenus écrits, les écritures supplémentaires non contrôlées corrompant la mémoire adjacente, ainsi que les connaissances limitées en matière de disposition des messages se sont avérés être un obstacle majeur à l'exploitation.
Au moment de l’analyse, seules les vulnérabilités de l’espace utilisateur impliquées dans le traitement initial d’un paquet de messages MSMQ ont été évaluées pour l’exploitabilité. L'analyse des vulnérabilités des variantes du noyau pourrait révéler d'autres possibilités d'exploitation. Par exemple, il est possible qu'un en-tête malformé obtienne une primitive d'écriture dans la cartographie de la mémoire du noyau du fichier . Dans certains cas, les contrôles du traitement de l'espace utilisateur empêchent le noyau d'effectuer certaines opérations de post-traitement.
De plus, dans le cas des variantes du noyau, le pirate informatique a moins de contrôle direct sur le contenu des messages et opère également sur le même mappage de fichiers que l'espace utilisateur, et non dans un pool du noyau (tas). Les mesures d'atténuation, telles que KASLR, présentent également des obstacles difficiles à surmonter pour une exploitation à distance.
En raison de la mise en oeuvre du code corrigé, un client distant peut déterminer en toute sécurité si un système a appliqué la mise à jour. Cela peut être fait en envoyant un message MSMQ qui déclenche la vulnérabilité, mais qui ne provoque pas réellement d’accès hors limites, évitant ainsi de bloquer le processus de service. Si l’indicateur HTTP est défini dans l’UserHeader du message, un SRMPEnvelopeHeader est attendu. Dans le correctif, une vérification d’un dépassement d’entier est effectuée sur le champ multiplié par 2. Cette longueur peut être déterminée de manière à ce que le résultat de la multiplication atteigne un petit nombre égal à la taille réelle des données.
Extrait de code décompilé montrant la vérification d'un dépassement d'entier sur SRMPEnvelopeHeader DataLength
Si la cible est corrigée, la vulnérabilité provoque une exception et le serveur interrompt le traitement du message, de sorte qu'aucune réponse n'est renvoyée au client. S'il n'est pas corrigé, le serveur traitera le message normalement et enverra une réponse.
En raison de la localisation de la mémoire des tampons vulnérables, l'exécution de code à distance semble plus facile pour un attaquant capable d'envoyer des messages à n'importe quelle file d'attente de la cible. Dans ce scénario, il est possible d’effectuer un nettoyage afin qu’un segment de mémoire adjacent soit alloué. Le contrôle extrêmement limité des contenus en écriture pose des problèmes pour l’exploitation à distance. En raison de mesures d'atténuation telles que l'ASLR, une fuite d'informations doit également être obtenue. Il est possible qu’une seule écriture d’une constante (0xC, 0x0
En fin de compte, nous concluons que si l'exploitation à distance de QueueJumper n'est pas impossible, les exigences susmentionnées la rendent difficile à réaliser. Cet article de blog ne fait qu'effleurer la surface d'une spécification de message, d'un service et d'un protocole très complexes. Il convient de poursuivre les recherches sur les vulnérabilités dans l'espace utilisateur et dans les opérations des composants du noyau.