
Technische Analyse und Proof-of-Concept-Exploit für CVE-2023-28252, eine Windows Common Log File System (CLFS)-Treiber-Privilegienausweitungsschwachstelle, die bei Nokoyawa-Ransomware-Angriffen verwendet wurde.
Seit Februar 2022 wurde eine neue Ransomware gemeldet, die offenbar eine Windows-0-Day-Schwachstelle ausnutzt, so die von Trend Micro durchgeführte Forschung.
Weitere Informationen zu dieser Ransomware finden Sie unter diesem Link.
Laut der Analyse von Kaspersky hat die Nokoyawa-Ransomware-Gruppe seit Juni 2022 andere Exploits eingesetzt, die den Common Log File System (CLFS)-Treiber angreifen, mit ähnlichen, aber unterschiedlichen Merkmalen, die alle mit einem einzigen Exploit-Entwickler verbunden sind.
Im April 2023, als Microsoft den Patch veröffentlichte, wurde die CVE-2023-28252 zugewiesen.
Zuvor, im Jahr 2022, wurde von uns ein ähnlicher Fehler in derselben Komponente untersucht und in diesem Blogbeitrag dokumentiert.
Um die Analyse durchführen zu können, ist es notwendig, das .blf-Dateiformat zu kennen, das von dem anfälligen Common Log File System-Treiber namens CLFS.sys verwaltet wird und sich im Treiberordner innerhalb von system32 befindet.
Weitere Informationen zu diesem Dateityp finden Sie unter den folgenden Links:
https://github.com/ionescu007/clfs-docs/blob/main/README.md
https://www.coresecurity.com/core-labs/articles/understanding-cve-2022-37969-windows-clfs-lpe
Diese Analyse wurde für Windows 11 21H2, clfs.sys Version 10.0.22000.1574 durchgeführt, obwohl sie auch auf Windows 10 21H2, Windows 10 22H2, Windows 11 22H2 und Windows Server 2022 funktioniert.
In früheren Windows-Versionen müssen einige Werte angepasst werden, da sonst ein BSOD auftreten würde.
Microsoft Patch Tuesday April 2023.
Sie können die Treiberversion wie gezeigt überprüfen
Als die Schwachstelle im April 2023 veröffentlicht wurde, begann ich zusammen mit Esteban Kazimirow mit dem Reversing des CLFS.sys-Treibers. In diesem Fall war es jedoch sehr schwierig, allein durch die Analyse des Patches abzuleiten, wo der Fehler lag und wie er ausgelöst werden kann, da die Ausnutzung sehr komplex ist.
Später erschien ein Blogbeitrag, dessen Autor anhand einer Malware-Stichprobe einige Teile des von HexRays dekompilierten Codes sowie einige Informationen zeigte, die uns die Richtung vorgaben, in die die Ausnutzung gehen musste.
Offensichtlich waren die bereitgestellten Informationen nicht vollständig, aber ohne diese Hilfe wäre es unwahrscheinlich gewesen, dass wir den PoC und später einen funktionierenden Exploit hätten erstellen können.
Um das Verständnis zu erleichtern, werden wir zuerst erklären, wie der PoC aufgebaut wird, und dann die Schwachstellenanalyse durchführen.
Dieser Blogbeitrag enthält zwei Abschnitte:
Aufbau des PoC:
1- Beschaffen der benötigten Kernel-Adressen für die Ausnutzung
2- Vorbereiten des Pfads zum Erstellen der .blf-Dateien:
3- Erstellen der „trigger blf“-Datei mit der Funktion CreateLogFile()
4- Erstellen der „trigger blf“-Datei
5- Beschaffen der Kernel-Adresse des BASE BLOCK von trigger blf
6- Aufrufen von AddLogContainer mit dem Handle von trigger blf
7- Vorbereiten der spray blf-Dateien
8- Vorbereiten des Speichers für das Spray
9- Auslösen des Fehlers
Debugging:
1- Überprüfen des Memory Sprays
2- Betrachten des RecordOffset[12] von trigger blf
3- Betrachten des iFlushBlock-Werts in der spray blf-Datei
4- Warum wird von BLOCK 1 SHADOW statt von BLOCK 0 CONTROL gelesen?
5- Warum ist die Prüfsumme in den spray blf-Dateien gleich null?
6- Abschluss der Ausnutzung.
7- Der eigentliche Patch
Ich werde eine Funktion namens InitEnvironment erstellen, um einige notwendige Kernel-Adressen zu erhalten.
Holen der EPROCESS-Adresse meines Prozesses und Speichern in der Variablen g_EProcessAddress, dann die EPROCESS-Adresse des SYSTEM-Prozesses und Speichern in system_EPROCESS, dann die EHTREAD-Adresse des Hauptthreads meines Prozesses und Speichern in g_EThreadAddress und schließlich die Adresse des PREVIOUS MODE, die in dieser Version des PoC nicht verwendet wird.

Diese Methode ist bekannt: Die GetObjectKernelAddress-Funktion ruft NtQuerySystemInformation zweimal auf, mit dem ersten Argument SystemExtendedHandleInformation. Der erste Aufruf erfolgt mit einer falschen Größe und gibt einen Fehler zurück, aber auch die korrekte Größe, die im zweiten Aufruf verwendet wird, um die Informationen aller Handles zu erhalten. Dann wird in einer Schleife die Information jedes Handles durchlaufen und im Feld Object des richtigen handleinfo die gesuchte Adresse im Kernel gefunden.

Ich benötige auch die Kernel-Adressen der folgenden von CLFS.sys exportierten Funktionen:
• ClfsEarlierLsn
• ClfsMgmtDeregisterManagedClient
Und die von NTOSKRNL.exe exportierten Funktionen
• RtlClearBit/PoFxProcessorNotification
• SeSetAccessStateGenericMapping
Um diese Adressen zu erhalten, wird eine ähnliche Methode verwendet, wie um die Kernel-Basis beider Module zu erhalten, indem NtQuerySystemInformation zweimal aufgerufen wird, aber in diesem Fall ist das erste Argument SYSTEM_INFORMATION_CLASS (im PoC verwenden wir die Funktion FindKernelModulesBase zu diesem Zweck).
Dann wird CLFS.sys und NTOSKRNL.exe als normale Module im Benutzermodus durch Aufruf von LoadLibrary geladen, die Adressen im Benutzermodus mit GetProcAddress ermittelt, dann die Imagebase von jedem abgezogen, um den Offset der Funktion zu erhalten, und schließlich jeder Offset zu den entsprechenden Kernel-Basen addiert, um die Kernel-Adressen aller benötigten Funktionen zu erhalten.

Ich erstelle eine Funktion namens createInitialTriggerBlfFile, die eine .blf-Datei generiert und schreibt.
Der Pfad, der als Argument in CreateLogFile verwendet wird, unterscheidet sich von einem normalen Pfad. Zum Öffnen der Datei 1280.blf im Ordner C:\Users\Public müssen wir z.B. den Pfad LOG:C:\Users\Public\1280 angeben. Dieser wird in der Variablen stored_name_CreateLog gespeichert.