
Analyse technique et exploit de preuve de concept pour CVE-2023-28252, une vulnérabilité d'élévation de privilèges dans le pilote Windows Common Log File System (CLFS) utilisée lors des attaques du rançongiciel Nokoyawa.
Depuis février 2022, un nouveau ransomware a été signalé, qui semble utiliser une vulnérabilité zero-day de Windows, selon les recherches menées par Trend Micro.
Plus d'informations sur ce ransomware peuvent être trouvées à ce lien.
Selon l'analyse de Kaspersky, le groupe de ransomware Nokoyawa a utilisé d'autres exploits ciblant le pilote Common Log File System (CLFS) depuis juin 2022, avec des caractéristiques similaires mais distinctes, tous liés à un seul développeur d'exploit.
En avril 2023, lorsque Microsoft a publié le correctif, le CVE-2023-28252 a été attribué.
Auparavant, en 2022, un bogue similaire dans le même composant a été recherché par nous, et documenté dans ce billet de blog.
Pour mener l'analyse, il est nécessaire de connaître le format de fichier .blf, qui est géré par le pilote Common Log File System vulnérable appelé CLFS.sys et qui se trouve dans le dossier des pilotes dans system32.
Plus d'informations sur ce type de fichier peuvent être trouvées dans les liens ci-dessous :
https://github.com/ionescu007/clfs-docs/blob/main/README.md
https://www.coresecurity.com/core-labs/articles/understanding-cve-2022-37969-windows-clfs-lpe
Cette analyse est réalisée pour Windows 11 21H2, clfs.sys version 10.0.22000.1574 bien qu'elle fonctionne également sur Windows 10 21H2, Windows 10 22H2, Windows 11 22H2 et Windows server 2022.
Dans les versions précédentes de Windows, il est nécessaire d'ajuster certaines valeurs, sinon nous produirions un BSOD.
Microsoft Patch Tuesday avril 2023.
Vous pouvez vérifier la version du pilote comme indiqué.
Lorsque la vulnérabilité a été publiée, en avril 2023, j'ai commencé avec Esteban Kazimirow à effectuer le reverse engineering du pilote CLFS.sys, bien que dans ce cas, analyser uniquement le correctif était très difficile pour déduire où se trouvait le bogue et comment le déclencher, car l'exploitation est très complexe.
Plus tard, un billet de blog est sorti dont l'auteur, à partir d'un échantillon de malware, a montré certaines parties du code décompilé par HexRays et quelques informations qui ont guidé la direction à prendre pour l'exploitation.
Évidemment, les informations fournies n'étaient pas complètes, mais sans cette aide, il aurait été peu probable d'arriver à construire le PoC puis un exploit fonctionnel.
Pour faciliter la compréhension, nous expliquerons d'abord comment construire le PoC, puis nous ferons l'analyse de la vulnérabilité.
Ce billet de blog contient deux sections :
Construction du PoC:
1- Obtenir les adresses noyau dont nous avons besoin pour l'exploitation.
2- Préparer le chemin pour créer les fichiers .blf :
3- Créer le fichier "trigger blf" en utilisant la fonction CreateLogFile()
4- Façonner le fichier "trigger blf"
5- Obtenir l'adresse noyau du BLOC DE BASE du trigger blf
6- Appeler AddLogContainer avec le handle du trigger blf
7- Préparer les fichiers spray blf
8- Préparer la mémoire pour effectuer le spray
9- Déclencher le bogue
Débogage :
1- Vérifier le spray mémoire
2- Regarder le RecordOffset[12] du trigger blf
3- Regarder la valeur iFlushBlock dans le fichier spray blf
4- Pourquoi lit-il à partir du BLOC 1 SHADOW au lieu du BLOC 0 CONTROL ?
5- Pourquoi la somme de contrôle est-elle égale à zéro dans les fichiers spray blf ?
6- Terminer l'exploitation.
7- Le vrai correctif
Je vais créer une fonction nommée InitEnvironment pour obtenir certaines adresses noyau nécessaires.
Obtenez l'adresse EPROCESS de mon processus et stockez-la dans la variable g_EProcessAddress, puis l'adresse EPROCESS du processus SYSTEM, et stockez-la dans system_EPROCESS, puis l'adresse EHTREAD du thread principal de mon processus, et je la stocke dans g_EThreadAddress et enfin l'adresse du PREVIOUS MODE qui dans cette version du PoC ne sera pas utilisée.

Cette méthode est bien connue, la fonction GetObjectKernelAddress appelle NtQuerySystemInformation deux fois avec le premier argument SystemExtendedHandleInformation, le premier appel est passé avec une taille incorrecte et retourne une erreur, mais retourne également la taille correcte qui est utilisée dans le second appel et obtient les informations de tous les handles, puis en parcourant dans une boucle les informations de chaque handle et dans le champ Object du handleinfo correct, elle obtient l'adresse recherchée dans le noyau.

J'ai aussi besoin des adresses noyau des fonctions suivantes exportées par CLFS.sys :
• ClfsEarlierLsn
• ClfsMgmtDeregisterManagedClient
Et les fonctions exportées de NTOSKRNL.exe
• RtlClearBit/PoFxProcessorNotification
• SeSetAccessStateGenericMapping
Pour obtenir ces adresses, on utilise une méthode similaire à celle utilisée pour obtenir la base noyau des deux modules, en appelant NtQuerySystemInformation deux fois, mais dans ce cas le premier argument sera SYSTEM_INFORMATION_CLASS (dans le PoC nous utilisons la fonction FindKernelModulesBase à cet effet).
Ensuite, il charge CLFS.sys et NTOSKRNL.exe en tant que modules normaux en mode utilisateur en appelant LoadLibrary, obtient les adresses en mode utilisateur avec GetProcAddress, puis soustrait la base d'image de chacun, ce qui donne le décalage de la fonction et enfin ajoute chaque décalage aux bases noyau correspondantes et obtient ainsi les adresses noyau de toutes les fonctions nécessaires.

Je crée une fonction appelée createInitialTriggerBlfFile qui va générer et écrire un fichier .blf.