
Proof Of Concept für CVE-2023-21716 Microsoft Word Heap Corruption
Im Februar 2023 schloss Microsoft eine kritische Sicherheitslücke in Microsoft Word, die als CVE-2023-21716 mit einem CVSS-Score von 9,8 identifiziert wurde, die es Angreifern ermöglichen könnte, ohne Authentifizierung Remote-Code auszuführen. Diese Sicherheitslücke betraf auch den Outlook-Vorschaubereich, was bedeutet, dass sie bereits durch das bloße Vorschauen der Datei ausgelöst werden kann. Obwohl Microsoft einen Patch und eine Problemumgehung veröffentlichte, gaben sie keine Details zu dem Problem preis. Am 6. März teilte der Forscher, der den Fehler entdeckte (Joshua J. Drake – @jduck), einen Proof of Concept (PoC) auf Twitter.
CVE-2023-21716 resultiert daraus, wie Microsoft Word Rich Text Format (RTF)-Dateien verarbeitet, insbesondere das Steuerwort \fonttbl, das Schriftarten im Dokument im Format \f definiert. Der \fonttbl innerhalb der wwlib.dll wird eine bestimmte Menge Speicherplatz auf dem Heap zugewiesen (Dies liegt daran, dass Heap-Allokationen typischerweise für dynamische Daten verwendet werden, wie das Parsen großer Strukturen wie einer Schriftartentabelle, deren Größe je nach Eingabe variieren kann). Der Absturz tritt aufgrund eines Pufferüberlaufs auf, wenn die Anzahl der Schriftarten das Limit überschreitet (vom PoC auf 32760 bestätigt). Das Überschreiten des zugewiesenen Heap-Speichers führt zum Überschreiben des Return Instruction Pointer (RIP), was den Absturz der Anwendung verursacht.
Benutzer werden dringend aufgefordert, die neuesten Sicherheitspatches von Microsoft zu installieren, da diese das Problem behoben haben. Für diejenigen, die nicht aktualisieren können, hat Microsoft auch mehrere Problemumgehungen bereitgestellt, die hier zu finden sind: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-21716.
Mit WinDbg können wir einen genaueren Blick darauf werfen, um die Ursache des Absturzes zu verstehen. Hier ist der Ablauf:
WinDbg wird automatisch anhalten, wenn der Absturz auftritt, sodass wir ihn weiter analysieren können. Zunächst können wir 'k' eingeben, um den Call Stack anzuzeigen:
0:000> k
# ChildEBP RetAddr
00 012f5134 77a5feb5 ntdll!RtlReportCriticalFailure+0x4b
01 012f5170 77a5dda9 ntdll!RtlpReportHeapFailure+0x2f
02 012f5170 77a66220 ntdll!RtlpHpHeapHandleError+0x89
03 012f5188 77a5dab7 ntdll!RtlpLogHeapFailure+0x43
04 012f51ec 779b400d ntdll!RtlpAnalyzeHeapFailure+0x281
05 012f5348 779f806d ntdll!RtlpFreeHeap+0x24d
06 012f53a4 779b3d66 ntdll!RtlpFreeHeapInternal+0x783
07 012f53c4 6ea4aa24 ntdll!RtlFreeHeap+0x46 //Die Funktionen unter ntdll beziehen sich auf die Fehlerbehandlung der Heap-Korruption
08 012f53d8 6ea4a9cb mso20win32client!Ordinal1068+0xab
09 012f53e8 6ea4a995 mso20win32client!Ordinal1068+0x52
0a 012f53f4 6cccda52 mso20win32client!Ordinal1068+0x1c
0b 012f5410 03657fea mso!Ordinal1387+0x24
0c 012f5424 03990115 wwlib!PTLS7::FsUpdateFinitePage+0x7e26f //wwlib ist für die Verwaltung der Schriftartentabelle zuständig
0d 012f5670 034ea593 wwlib!PTLS7::LsDestroyContext+0x245f90
0e 012f6f5c 033a68ef wwlib!PTLS7::FsUpdateBottomlessPage+0x17494
0f 012f7484 035054ed wwlib!PTLS7::LsAssert+0x2bd1c
10 012f888c 03503d3b wwlib!PTLS7::FsUpdateBottomlessPage+0x323ee
11 012f8910 0400be52 wwlib!PTLS7::FsUpdateBottomlessPage+0x30c3c
12 012f9e9c 0390013a wwlib!wdGetApplicationObject+0xdf8a0
13 012faf48 03ebf20e wwlib!PTLS7::LsDestroyContext+0x1b5fb5
14 012faf90 0410ab2a wwlib!DllCanUnloadNow+0xcc314
15 012fcfe0 03752fb4 wwlib!wdGetApplicationObject+0x1de578
16 012ff538 03385b93 wwlib!PTLS7::LsDestroyContext+0x8e2f
17 012ff578 75e6173b wwlib!PTLS7::LsAssert+0xafc0
18 012ff5a4 75e57eaa USER32!_InternalCallWinProc+0x2b
19 012ff68c 75e57eaa USER32!UserCallWinProcCheckWow+0x33a
1a 012ff6c4 75e57666 USER32!CallWindowProcAorW+0x7f
1b 012ff6dc 75e55e8b USER32!CallWindowProcW+0x1b
.....
.....
Unsere beiden Schlüsselbibliotheken sind wwlib.dll, eine zentrale Word-Bibliothek, die Dokumentinhalte wie Schriftarten, Text und Layout verwaltet, und ntdll.dll, die systemnahe Aufgaben wie Speicherverwaltung und Fehlerbehandlung übernimmt. Der Absturz tritt auf, wenn Word eine große Anzahl von Schriftarten aus der RTF-Datei verarbeitet. Wenn ntdll.dll erkennt, dass Word versucht, auf ungültigen Speicher zuzugreifen oder ihn freizugeben (wahrscheinlich aufgrund des Schriftartenüberlaufs korrupt), löst es einen Heap-Korruptionsfehler aus, der zum Absturz führt.
Um tiefer zu graben, können wir einen Breakpoint im letzten Teil der wwlib-Bibliothek setzen, um zu sehen, wie unsere Schriftarten in den Speicher geladen werden, und zu verstehen, was das Problem ausgelöst hat:
bc * //alle anderen Breakpoints löschen
bp wwlib!PTLS7::FsUpdateFinitePage+0x7e26f //Breakpoint setzen
Wir erhalten nun eine Zugriffsverletzung:
(ba4.1a14): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=004f1ce4 ebx=00000001 ecx=000004e4 edx=ffff7ffc esi=13474fe8 edi=00008002
eip=02b300d5 esp=004f1c3c ebp=004f1c48 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210206
wwlib!PTLS7::FsUpdateFinitePage+0x7635a:
02b300d5 66894c5604 mov word ptr [esi+edx*2+4],cx ds:002b:13464fe4=???? //Der Break erfolgt hier
Da wir das Programm früher angehalten haben, an dem Punkt, an dem wwlib.dll zum ersten Mal versucht, auf ungültigen Speicher zuzugreifen oder diesen zu ändern (in FsUpdateFinitePage), können wir die anfängliche Zugriffsverletzung sehen (die die Speicherkorruption verursacht), was uns die Möglichkeit gibt, zu untersuchen, was schiefgelaufen ist, bevor der Heap-Korruptionsfehler von ntdll.dll erkannt wird.
Genauer gesagt, das Programm wurde aufgrund einer Zugriffsverletzung (Code c0000005) an der Instruktion mov word ptr [esi+edx2+4],cx innerhalb der Funktion wwlib!PTLS7::FsUpdateFinitePage+0x7635a angehalten. Dieser Fehler zeigt an, dass Word versucht hat, auf eine ungültige Speicheradresse zuzugreifen, insbesondere beim Versuch, einen Wert (cx) in den Speicher an der Adresse esi+edx2+4 zu schreiben.
Wenn wir uns das ESI-Register genauer ansehen, können wir sehen, dass es die Schriftartendaten enthält:
Jeder 16-Bit-Wert (zwei Bytes) im Little-Endian-Format repräsentiert einen Schriftarteintrag im Format \fA;
Der letzte Wert, der im ESI dargestellt wird, ist f8 7f, was {\f32760A;} entspricht, bevor wir zum Ende gelangen (symbolisiert durch 29-00)

Nachdem nun die Schriftartentabelle in den Speicherbereich geladen wurde, auf den das ESI-Register zeigt, wird bei einer so großen Anzahl verarbeiteter Schriftarten die berechnete Speicheradresse (esi + edx*2 + 4) wahrscheinlich den für die Schriftartentabelle zugewiesenen Speicher überschreiten. Dies führt zu einem Schreibzugriff außerhalb der Grenzen, was einen Zugriffsverletzungsfehler verursacht. Die Zugriffsverletzung wird von ntdll.dll erkannt, die die Speicherverwaltung und Fehlerberichterstattung übernimmt. Infolgedessen ruft ntdll.dll Funktionen auf, die Heap-Korruption erkennen, was letztendlich zum Absturz der Anwendung führt.