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
my-CVE-2021-1675 — Analyse détaillée et implémentation d'exploit pour Windows PrintNightmare (CVE-2021-1675/34527) avec élévation de privilèges basée sur RPC et exécution de code à distance via l'installation d'un pilote d'imprimante malveillant. | Kitploit
Outils/GitHubGitHub/hahaleyile/my-cve-2021-1675
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationArticles et RechercheApprentissage et ÉducationOutil d'Accès à DistanceExploitation de Binaires
GitHubhahaleyile/my-cve-2021-1675

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

my-CVE-2021-1675

Analyse détaillée et implémentation d'exploit pour Windows PrintNightmare (CVE-2021-1675/34527) avec élévation de privilèges basée sur RPC et exécution de code à distance via l'installation d'un pilote d'imprimante malveillant.

Voir le dépôt
331il y a 5 ansPas encore vérifié

= Rapport d'analyse de Print Nightmare :imagesdir: Figures :toc: :icons: font :figure-caption: Figure :xrefstyle: short :pdf-theme: basic-theme.yml

Le 29 juin 2021, une vulnérabilité très grave du service d'impression Windows a été exposée en tant que 0day, avec un score de base de 8,8 ; l'exploit a été publié sur GitHub (depuis supprimé). Cette vulnérabilité est la célèbre PrintNightmare : CVE-2021-34527, dont le niveau de dangerosité dépasse même celui d'EternalBlue.

== Informations de base sur la vulnérabilité

La vulnérabilité 34527 affecte pratiquement toutes les versions à partir de Windows 7 et Windows Server 2008 ; voir <> pour plus de détails.

Du point de vue de l'impact, un attaquant peut, avec une authentification d'utilisateur ordinaire, exécuter du code arbitraire à distance avec des privilèges administrateur. En ce qui concerne la difficulté d'exploitation, cette vulnérabilité est très facile à exploiter et présente donc un danger considérable.

En ce qui concerne les caractéristiques de la vulnérabilité, la vulnérabilité 34527 est basée sur la vulnérabilité CVE-2021-1675. La vulnérabilité 1675 est une vulnérabilité d'élévation de privilèges locale et d'exécution de code à distance ; elle présente de très grandes similitudes avec la vulnérabilité 34527.

Avant de comprendre le principe de fonctionnement de la vulnérabilité, il convient d'avoir une compréhension approximative de l'architecture du spooler d'impression Windows, ce qui nous permettra de clarifier les relations entre les différents modules impliqués dans la vulnérabilité.

== Flux d'appel de CVE-2021-1675

=== Architecture du spooler d'impression Windows

L'architecture du spooler peut être représentée par <<spooler_arch>> :

[[spooler_arch]] .Architecture du spooler d'impression image::Print Spooler Architecture.png[]

Plus précisément, le spooler d'impression sert à gérer les tâches d'impression et se compose des éléments suivants :

winspool.drv:: Bibliothèque de liens dynamiques fournie à l'utilisateur. Ce fichier définit les API Win32 liées au spooler pour que les utilisateurs puissent les appeler. Toutes les API qu'il contient utilisent l'appel de procédure distante pour obtenir les services.

spoolsv.exe:: spoolsv.exe joue le rôle de serveur dans l'architecture, en tant que premier programme à traiter les appels d'API. Cette conception permet au spooler d'impression de traiter à la fois les travaux d'impression locaux et les travaux d'impression distants sans distinction.

spoolsv.dll:: Programme de routage. Il achemine les requêtes d'impression reçues par spoolsv.exe vers les différents fournisseurs d'impression et détermine quel fournisseur d'impression traitera finalement la requête. Son rôle est de distinguer si une tâche d'impression est distante ou locale. Sur une machine distante, il affecte la tâche au fournisseur d'impression local.

localspl.dll:: Fournisseur d'impression local. Le rôle principal du fournisseur d'impression est de répondre aux besoins de gestion des tâches d'impression ; la grande majorité des API sont implémentées dans ce module.

En poursuivant l'étude selon la théorie ci-dessus, prenons un exemple : lorsque j'appelle la fonction AddPrinterDriverEx (CVE-2021-1675), le flux suivant est suivi :

=== Sélection de la version de la fonction

Tout d'abord, cette fonction est en réalité une macro qui sélectionne la version Unicode (W) ou Ansi (A) en fonction de l'environnement de compilation local, comme <> :

[[AddPrinterDriverEx]] .AddPrinterDriverEx image::AddPrinterDriverEx.png[]

Mais qu'il s'agisse de la version à caractères larges ou à caractères étroits, le résultat est en fait identique, car les chaînes du noyau Windows sont encodées en Unicode ; l'appel de la version Ansi sera donc finalement converti en un appel de la version Unicode, comme <> :

[[AnsiToUnicode]] .AnsiToUnicode image::AnsiToUnicode.png[]

Une fois que tous les paramètres de la fonction Ansi sont convertis en version Unicode, une fonction est appelée (<>) :

[[AnsiCallUnicode]] .AnsiCallUnicode image::AnsiCallUnicode.png[]

Cette fonction n'est en réalité que la version Unicode d'AddPrinterDriverEx (<>) :

[[GetUnicodeProcAddress]] .GetUnicodeProcAddress image::GetUnicodeProcAddress.png[]

=== La fonction API envoie une requête RPC au serveur spooler

Une fois à l'intérieur de la fonction en version Unicode, une sélection du type des paramètres de la fonction est d'abord effectuée en fonction de la valeur de Level :

image::pDriverInfo.png[]

Dans cette vulnérabilité, nous définissons Level à 2, ce qui sélectionne le type du paramètre pDriverInfo comme étant la structure DRIVER_INFO_2. Ensuite, Windows traite les paramètres de la fonction et, une fois le traitement terminé, poursuit le traitement de cette API via un appel de procédure distante :

image::set arguments.png[]

image::NdrClientCall3.png[]

=== Mécanisme MSRPC

Le mécanisme d'appel de procédure distante de Microsoft est construit sur la norme DCE. En termes simples, l'appel de procédure distante consiste à exécuter des processus sur un système distant, ces processus étant prédéfinis par les programmeurs ou par le système.

Concrètement, RPC consiste à sérialiser la fonction que l'on souhaite appeler à distance, à la transmettre via le réseau vers le système distant, qui la désérialise puis l'exécute. Dans l'architecture construite par Microsoft, TCP/IP et SMB sont les protocoles habituellement choisis pour transporter les appels RPC.

Pour utiliser MSRPC, il faut d'abord définir la description d'interface IDL de la fonction à appeler, puis utiliser l'outil MIDL pour générer les stubs de sérialisation correspondants côté client et côté serveur. Pour certaines API Win32, le stub serveur est déjà défini par défaut ; il suffit donc de générer et d'utiliser le stub client.

MSRPC utilise un UUID pour identifier un type de protocole. Par exemple, MS-RPRN est utilisé pour décrire le protocole d'impression à distance ; toutes les fonctions liées à l'impression à distance font partie de ce protocole. MSRPC utilise l'UUID 12345678-1234-ABCD-EF00-0123456789AB pour identifier ce protocole (<<rprn_uuid>>) :

[[rprn_uuid]] .UUID MS-RPRN image::spoolss uuid.png[]

Ensuite, toujours sur la base de cette connexion, on peut utiliser le numéro d'opération (opnum) pour identifier les fonctions du protocole et les appeler à distance. Par exemple, AddPrinterDriverEx s'identifie par le numéro 89 (<<addPrinterDriverEx_opnum>>) :

[[addPrinterDriverEx_opnum]] .Opnum AddPrinterDriverEx image::AddPrinterDriverEx Opnum.png[]

Lors de l'utilisation de MSRPC, deux points méritent une attention particulière :

[IMPORTANT]

  • La connexion TCP/IP utilise un port dynamique, dont la valeur doit être obtenue via l'endpoint mapper qui écoute sur le port 135.

"As you can see in your output, the scripts are trying to connect to port 135 (endpoint mapper) in order to get the TCP/IP port where the DCOM endpoint is listening (that is a dynamic port)." -- SecureAuthCorp/impacket issue #412

  • Par ailleurs, certaines fonctions RPC nécessitent une authentification pour être appelées, c'est pourquoi cette vulnérabilité requiert les privilèges d'un utilisateur ordinaire. ====

=== spoolsv.exe traite les requêtes API

[[call_flow]] .Flux d'appel de RpcAddPrinterDriverEx image::Function Calls.png[]

Comme le montre <<call_flow>>, spoolsv.exe appelle ces fonctions, et d'après l'analyse interne des fonctions, ce module n'effectue aucune opération en dehors de l'initialisation. Enfin, ce module appelle la fonction pointée par pLocalProvidor, c'est-à-dire la fonction LocalAddPrinterDriverEx du module localspl.dll. En tant que fournisseur d'impression local, localspl est bien le module qui implémente les fonctionnalités de l'API.

=== Logique d'implémentation des fonctions du fournisseur d'impression local

[[LocalAddPrinterDriverEx]] .LocalAddPrinterDriverEx image::LocalAddPrinterDriverEx.png[]

Tout d'abord, <> montre que ce module vérifie que le spooler fonctionne normalement, puis saute vers la fonction SplAddPrinterDriverEx.

[[SplAddPrinterDriverEx]] .SplAddPrinterDriverEx image::SplAddPrinterDriverEx.png[]

L'intérieur de la fonction <> est l'endroit clé qui détermine si la fonction AddPrinterDriverEx peut s'exécuter avec succès. La première moitié n'a pas besoin d'être examinée, car WPP est une technologie liée à la journalisation ; passons-la pour l'instant.

Dans la seconde moitié, Microsoft définit une variable v12, un indicateur (flag) qui détermine si la fonction continue de s'exécuter ou se termine directement.

[[bittest]] .bittest dwFileCopyFlags image::bittest in spl.png[]

Comme on peut le voir dans <>, il existe deux conditions pour continuer l'exécution : soit v12 vaut 0, c'est-à-dire que le test bittest réussit, soit la validation (Validate) réussit. Or Validate est une vérification des privilèges qu'il n'est pas aisé de contourner. Elle contient une API, OpenProcessToken, qui indique que les privilèges doivent être élevés dans le processus suivant ; impossible à réaliser sans être administrateur.

Pour continuer l'exécution, il faut donc contourner la vérification de bittest. La valeur testée, a4 — le 4e paramètre de la fonction — est le paramètre documenté sur le site officiel <> :

|=== |Nom/valeur |Description

|APD_STRICT_UPGRADE

0x00000001

|Ajouter le pilote d'impression de remplacement uniquement si aucun des fichiers du pilote de remplacement n'est plus ancien que les fichiers correspondants du pilote actuellement installé.

|APD_STRICT_DOWNGRADE

0x00000002

|Ajouter le pilote d'impression de remplacement uniquement si aucun des fichiers du pilote actuellement installé n'est plus ancien que les fichiers correspondants du pilote de remplacement.

|APD_COPY_ALL_FILES

0x00000004

|Ajouter le pilote d'impression et copier tous les fichiers du répertoire du pilote. Les horodatages des fichiers DOIVENT être ignorés.

|APD_COPY_NEW_FILES

0x00000008

|Ajouter le pilote d'impression et copier les fichiers du répertoire du pilote qui sont plus récents que les fichiers correspondants actuellement utilisés.

|APD_COPY_FROM_DIRECTORY

0x00000010

|Ajouter le pilote d'impression en utilisant les noms de fichiers complets spécifiés dans la structure _DRIVER_INFO_6. Si cet indicateur est spécifié, l'un des autres indicateurs de copie de ce champ de bits DOIT être spécifié.

|APD_DONT_COPY_FILES_TO_CLUSTER

0x00001000

|Lors de l'ajout d'un pilote d'impression à un cluster de serveurs d'impression, ne pas copier les fichiers du pilote sur le disque partagé du cluster.

|APD_COPY_TO_ALL_SPOOLERS

0x00002000

|Ajouter le pilote d'impression aux serveurs de spooler du cluster.

|APD_INSTALL_WARNED_DRIVER

0x00008000

|Ajouter le pilote d'impression, même s'il figure dans la liste des pilotes d'impression sous avertissement du serveur.

|APD_RETURN_BLOCKING_STATUS_CODE

0x00010000

|Spécifie le code d'erreur spécifique à l'implémentation à renvoyer si le pilote d'impression est bloqué lors de l'installation par la stratégie du serveur.

|===

bittest 16 vérifie si le 16e bit de la variable vaut 1, ce qui correspond à la valeur de paramètre 0x8000 (APD_INSTALL_WARNED_DRIVER). La définition montre également que ce paramètre signifie que le pilote d'impression est ajouté au serveur sans vérification.

On raconte qu'avant la correction de la vulnérabilité 1675, ce paramètre n'apparaissait pas encore dans la documentation officielle ; il n'est pas difficile d'y voir l'origine de la vulnérabilité.

=== Méthode d'exploitation de la vulnérabilité

Lorsque la méthode d'ajout de pilote d'impression s'exécute réellement, si la structure DRIVER_INFO_2 est choisie, les événements suivants se produisent :

. Les fichiers DriverFile, ConfigFile et DataFile sont ouverts séparément pour confirmer que ces trois fichiers existent. Seul DataFile peut être un chemin UNC.

ifdef::backend-pdf[] Le résultat d'exécution du programme malveillant est détaillé dans https://github.com/hahaleyile/my-CVE-2021-1675[mon dépôt] ; la démonstration animée est le fichier gif du répertoire Figures. endif::[]

== Correctif de Microsoft pour la vulnérabilité 1675

Le 8 juin 2021, Microsoft a corrigé la vulnérabilité CVE-2021-1675, avec les modifications suivantes :

[[path_1675]] .Correctif CVE-2021-1675 image::IsElevated.png[]

[[YIsElevationRequired]] .YIsElevationRequired image::YIsElevationRequired.png[]

[[YIsElevated]] .YIsElevated image::YIsElevated.png[]

[[unset_1675]] .Désactivation d'APD_INSTALL_WARNED_DRIVER image::JudgeIsElevated.png[]

Microsoft a ajouté une vérification de l'élévation des privilèges de l'utilisateur dans la fonction RpcAddPrinterDriverEx, et l'utilisateur peut supprimer cette restriction via le registre (<<path_1675>>). Il suffit à l'utilisateur de créer une clé nommée NoWaringNoElevationOnInstall à l'emplacement spécifié du registre (<>), ou que le compte RPC puisse obtenir le jeton de processus TOKEN_QUERY (<>), pour contourner ce correctif. Si le correctif est appliqué, le 16e bit du paramètre dwFileCopyFlags sera mis à 0 par une opération AND, ce qui signifie que la valeur du paramètre APD_INSTALL_WARNED_DRIVER sera invalidée (<<unset_1675>>).

== Contournement du correctif de 1675

Bien que Microsoft ait appliqué un correctif à la fonction RpcAddPrinterDriverEx, nous pouvons toujours le contourner via l'appel distant RpcAsyncAddPrinterDriver. Comme le montre <<async_send>>, la fonction côté client est un appel distant direct vers le serveur :

[[async_send]] .Envoi RpcAsyncAddPrinterDriver image::RpcAsyncAddPrinterDriver Send.png[]

Le serveur alloue d'abord un espace pour le thread, puis poursuit l'appel, comme le montre <<async_receive>> :

[[async_receive]] .Réception RpcAsyncAddPrinterDriver image::RpcAsyncAddPrinterDriver Receive.png[]

La fonction appelée en continu empile tous les paramètres sur la pile et exécute YAddPrinterDriverEx sous forme de thread (<<async_yadd>>) :

[[async_yadd]] .Démarrage du thread YAddPrinterDriverEx image::thread start YAddPrinterDriverEx.png[]

Cela permet de contourner avec succès le correctif de Microsoft sur RpcAddPrinterDriverEx.

En d'autres termes, en appelant à distance la fonction RpcAsyncAddPrinterDriver, on peut continuer à exécuter du code arbitraire en tant qu'administrateur.

De plus, selon <>, le correctif comporte encore des problèmes dans sa vérification du jeton (Token), et sur les machines où UAC est totalement désactivé, ce correctif sera inefficace. Cependant, je ne connais pas très bien les mécanismes de cet aspect, je ne ferai donc pas de commentaires supplémentaires.

Télécharger l’outil

. Si les trois fichiers existent, ils sont copiés dans le répertoire C:\Windows\System32\spool\drivers\x64\3\New, comme le montrent <<cp_conf_file>> et <<cp_data_file>> : + [[cp_conf_file]] .Copie du fichier de configuration image::copy config file.png[] + [[cp_data_file]] .Copie du fichier de données image::copy data file.png[]

. La raison de la copie dans ce répertoire est d'exécuter les fichiers correspondants ; le 3 indique que ce pilote d'impression est un pilote de type v3. Les nouveaux fichiers sont d'abord copiés dans le répertoire New pour éviter d'écraser les fichiers du répertoire 3. Si un fichier du même nom existe dans 3, le fichier du même nom est déplacé vers le répertoire Old en guise de sauvegarde, puis les fichiers de New sont copiés dans 3 pour écraser les fichiers. On peut l'observer lors de la deuxième exécution de la méthode RpcAddPrinterDriverEx : + .Deuxième appel RPC image::second time call.png[] + .Sauvegarde des fichiers vers le répertoire Old image::backup file.png[] + .Copie des nouveaux fichiers vers la destination image::copy file.png[] + Grâce à ce mécanisme, nous pouvons enregistrer un fichier situé sur un chemin distant en tant que fichier en chemin local, car parmi les paramètres de la fonction, les paramètres de fichier pilote et de fichier de configuration ne peuvent être que des chemins locaux ; seul le paramètre de fichier de données peut être un chemin distant.

. Selon <>, pConfigFile est la bibliothèque de liens dynamiques de configuration du pilote de périphérique ; elle doit donc être chargée une fois pour l'initialisation. Ce point est également confirmé par le comportement observé lors de l'exécution réelle. + .Chargement de pConfigFile image::Load Image.png[] + Ainsi, il suffit d'écrire une DLL malveillante et de placer le code malveillant au point d'entrée de la DLL pour exécuter du code arbitraire, avec les privilèges administrateur en plus. + .spoolsv.exe s'exécute avec les privilèges administrateur image::spoolsv user.png[]

. La fonction CreateInternalDriverFileArray() détermine, en fonction de l'indicateur d'opération sur les fichiers, s'il faut vérifier le répertoire des pilotes spool. Si l'indicateur (flag) a5 est défini sur False, la fonction de chargement du pilote ne vérifie que si le répertoire utilisateur contient les fichiers du pilote à copier. Sinon, la fonction tente de rechercher le pilote cible dans le répertoire des pilotes spool. Cela implique que dwFileCopyFlags doit également définir le paramètre APD_COPY_FROM_DIRECTORY. + image::APD.png[] + image::APD_1.png[]

[TIP]

En résumé, l'approche d'exploitation du code malveillant est la suivante : utiliser la DLL malveillante comme fichier de configuration (configfile) pour l'initialisation, ce qui exécutera du code arbitraire avec les privilèges administrateur. Il suffit d'ouvrir un partage samba sur la machine de l'attaquant pour que la machine victime télécharge le programme malveillant sous forme de fichier de données (datafile) et l'exécute.

== Utilisation du programme d'exploitation

Ce programme est construit sur la base de docker, ce qui permet de résoudre efficacement les problèmes de dépendances d'environnement.

Tout d'abord, l'utilisateur télécharge le fichier compose dans son propre répertoire, puis crée un dossier share dans ce répertoire comme répertoire de montage. L'utilisateur peut placer le programme malveillant dans le dossier share, qui sera partagé en tant que chemin samba smb.

Ensuite, l'utilisateur saisit la commande dans le terminal

[source,docker]

docker-compose up -d

pour démarrer le cluster (un conteneur). L'utilisateur peut entrer lui-même dans le conteneur pour opérer ; l'environnement du conteneur est déjà entièrement configuré.

Il est également possible de saisir directement la commande dans le terminal

[source,docker]

docker-compose run my_cve python main.py -h

pour exécuter la commande.

== Résultat d'exécution du programme d'exploitation

Merci à <> pour le code open source mis à ma disposition !

ifndef::backend-pdf[] .Résultat d'exécution du programme image::exploit.gif[] endif::[]

== Correctif de Microsoft pour la vulnérabilité 34527

Le 6 juillet 2021, Microsoft a temporairement résolu ce problème de vulnérabilité du spooler d'impression par une nouvelle série de correctifs.

Selon la déclaration officielle, ce correctif fera en sorte que l'installation de pilotes d'impression sur un serveur d'impression ne puisse être effectuée que par un administrateur. De plus, Microsoft a ajouté une stratégie de groupe et deux clés de registre pour permettre aux utilisateurs de personnaliser cette stratégie.

En observant la décompilation ida de <<restrict_async>>, nous pouvons voir que Microsoft a ajouté de nouvelles vérifications du jeton (Token) et des entrées de registre dans la fonction Async.

[[restrict_async]] .Restriction dans la fonction async image::restrict in async.png[]

Grâce à <<restrict_rpcadd>>, nous pouvons voir que Microsoft a ajouté des vérifications sur le groupe d'utilisateurs et ses clés de registre dans la fonction RpcAddPrinterDriverEx.

[[restrict_rpcadd]] .Restriction dans la fonction RpcAddPrinterDriverEx image::restrict in rpcadd.png[]

Par conséquent, il semble bien que le correctif de la vulnérabilité 1675 comporte effectivement encore des problèmes de vérification du jeton (Token).

== Plan du projet

. Ajouter la prise en charge de l'appel distant RpcAsyncAddPrinterDriver afin de contourner le correctif de Microsoft du 8 juin et de réaliser l'exploit CVE-2021-34527.

. Comprendre le mécanisme UAC et compléter cette analyse de vulnérabilité.

[bibliography] == Références

  • [[[a,Site officiel]]] Vulnérabilité d'exécution de code à distance du spooler d'impression Windows https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-34527

  • [[[b,dwFileCopyFlags]]] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b

  • [[[c,Analyse de la vulnérabilité Windows PrintNightmare (CVE-2021-34527) et de son correctif]]] https://www.freebuf.com/vuls/279876.html

  • [[[d,gentilkiwi/mimikatz]]] https://github.com/gentilkiwi/mimikatz

  • [[[e,Documentation officielle]]] Structure DRIVER_INFO_2 https://docs.microsoft.com/en-us/windows/win32/printdocs/driver-info-2

  • [[[f,cube0x0]]] https://github.com/cube0x0

  • [[[g,James Forshaw]]] https://twitter.com/tiraniddo/status/1410726790994169857

  • [[[h,Déclaration officielle]]] KB5005010 : Restriction de l'installation de nouveaux pilotes d'impression après l'application des mises à jour du 6 juillet 2021 https://support.microsoft.com/en-us/topic/kb5005010-restricting-installation-of-new-printer-drivers-after-applying-the-july-6-2021-updates-31b91c02-05bc-4ada-a7ea-183b129578a7