Heap Overflow
Grundlegende Informationen
Ein Heap Overflow ist wie ein Stack Overflow, aber im Heap. Grundsätzlich bedeutet dies, dass im Heap etwas Platz reserviert wurde, um einige Daten zu speichern, und die gespeicherten Daten größer waren als der reservierte Platz.
Bei Stack Overflows wissen wir, dass einige Register wie der Instruktionszeiger oder der Stackrahmen vom Stapel wiederhergestellt werden und es möglich sein könnte, dies auszunutzen. Im Falle von Heap Overflows wird standardmäßig keine sensible Information im Heap-Chunk gespeichert, der überlaufen werden kann. Es könnte jedoch sensible Informationen oder Zeiger geben, sodass die Kritikalität dieser Schwachstelle davon abhängt, welche Daten überschrieben werden können und wie ein Angreifer dies ausnutzen könnte.
Um Überlauf-Offsets zu finden, können Sie dieselben Muster wie bei Stack Overflows verwenden.
Stack Overflows vs. Heap Overflows
Bei Stack Overflows ist die Anordnung und die Daten, die zum Zeitpunkt auftreten, an dem die Schwachstelle ausgelöst werden kann, im Stapel ziemlich zuverlässig. Dies liegt daran, dass der Stapel linear ist, sich immer in kollidierendem Speicher erhöht, an spezifischen Stellen des Programmablaufs der Stapelspeicher normalerweise ähnliche Daten speichert und eine spezifische Struktur mit einigen Zeigern am Ende des Stapelteils hat, die von jeder Funktion verwendet werden.
Im Falle eines Heap Overflows ist der verwendete Speicher jedoch nicht linear, sondern die allokierten Chunks befinden sich normalerweise an getrennten Speicherpositionen (nicht nebeneinander), aufgrund von Bins und Zonen, die Allokationen nach Größe trennen, und weil zuvor freigegebener Speicher verwendet wird, bevor neue Chunks allokiert werden. Es ist kompliziert zu wissen, welches Objekt mit dem überlaufenden Objekt kollidieren wird. Wenn also ein Heap Overflow gefunden wird, muss ein zuverlässiger Weg gefunden werden, um das gewünschte Objekt so zu platzieren, dass es im Speicher direkt neben dem überlaufenden Objekt liegt.
Eine der Techniken, die dafür verwendet wird, ist Heap Grooming, die beispielsweise in diesem Beitrag verwendet wird. Im Beitrag wird erklärt, wie im iOS-Kernel, wenn eine Zone keinen Speicher mehr hat, um Speicherblöcke zu speichern, sie um eine Kernelseite erweitert wird, und diese Seite in Chunks der erwarteten Größen aufgeteilt wird, die in aufeinanderfolgender Reihenfolge verwendet werden (bis iOS-Version 9.2, dann werden diese Chunks auf eine randomisierte Weise verwendet, um die Ausnutzung dieser Angriffe zu erschweren).
Daher, in dem vorherigen Beitrag, in dem ein Heap Overflow auftritt, werden mehrere kallocs
durch mehrere Threads erzwungen, um sicherzustellen, dass alle freien Chunks gefüllt sind und eine neue Seite erstellt wird.
Um diese Füllung mit Objekten einer bestimmten Größe zu erzwingen, ist die Out-of-Line-Allokation, die mit einem iOS-Mach-Port verbunden ist, ein idealer Kandidat. Durch die Gestaltung der Größe der Nachricht ist es möglich, die Größe der kalloc
-Allokation genau anzugeben, und wenn der entsprechende Mach-Port zerstört wird, wird die entsprechende Allokation sofort an kfree
zurückgegeben.
Dann können einige dieser Platzhalter freigegeben werden. Die kalloc.4096
-Freiliste gibt Elemente in einer Last-In-First-Out-Reihenfolge frei, was im Grunde bedeutet, dass wenn einige Platzhalter freigegeben werden und der Exploit versucht, mehrere Opferobjekte zu allozieren, während er versucht, das Objekt, das anfällig für Überlauf ist, zu allozieren, ist es wahrscheinlich, dass dieses Objekt von einem Opferobjekt gefolgt wird.
Beispiel libc
Auf dieser Seite ist es möglich, eine grundlegende Emulation eines Heap Overflows zu finden, die zeigt, wie durch Überschreiben des prev-in-use-Bits des nächsten Chunks und der Position der prev-Größe ein benutzter Chunk konsolidiert werden kann (indem er denkt, er sei unbenutzt) und dann erneut allokiert werden kann, wodurch Daten überschrieben werden, die in einem anderen Zeiger verwendet werden.
Ein weiteres Beispiel aus protostar heap 0 zeigt ein sehr einfaches Beispiel eines CTF, bei dem ein Heap Overflow missbraucht werden kann, um die Gewinnerfunktion aufzurufen und die Flagge zu erhalten.
Im protostar heap 1 Beispiel ist zu sehen, wie durch Ausnutzen eines Pufferüberlaufs es möglich ist, in einem nahegelegenen Chunk eine Adresse zu überschreiben, an die beliebige Daten vom Benutzer geschrieben werden sollen.
Beispiel ARM64
Auf der Seite https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/ finden Sie ein Beispiel für einen Heap Overflow, bei dem ein Befehl, der ausgeführt werden soll, im folgenden Chunk vom überlaufenen Chunk gespeichert ist. Daher ist es möglich, den ausgeführten Befehl zu ändern, indem er mit einem einfachen Exploit überschrieben wird, wie z.B.:
Weitere Beispiele
Wir nutzen eine Integer-Überlauf-Schwachstelle, um einen Heap-Überlauf zu erhalten.
Wir manipulieren Zeiger auf eine Funktion innerhalb einer
struct
des überlaufenden Chunks, um eine Funktion wiesystem
festzulegen und Codeausführung zu erhalten.
Last updated