Stack Canaries
Last updated
Last updated
Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Lerne & übe GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
StackGuard fügt einen speziellen Wert, bekannt als canary, vor dem EIP (Extended Instruction Pointer) ein, speziell 0x000aff0d
(repräsentiert null, Zeilenumbruch, EOF, Wagenrücklauf), um gegen Pufferüberläufe zu schützen. Funktionen wie recv()
, memcpy()
, read()
und bcopy()
bleiben jedoch anfällig, und es schützt nicht den EBP (Base Pointer).
StackShield verfolgt einen ausgefeilteren Ansatz als StackGuard, indem es einen Global Return Stack beibehält, der alle Rückgabewerte (EIPs) speichert. Diese Einrichtung stellt sicher, dass ein Überlauf keinen Schaden anrichtet, da sie einen Vergleich zwischen gespeicherten und tatsächlichen Rückgabewerten ermöglicht, um Überlaufereignisse zu erkennen. Darüber hinaus kann StackShield die Rückgabeadresse mit einem Grenzwert überprüfen, um festzustellen, ob der EIP außerhalb des erwarteten Datenraums zeigt. Diese Schutzmaßnahme kann jedoch durch Techniken wie Return-to-libc, ROP (Return-Oriented Programming) oder ret2ret umgangen werden, was darauf hinweist, dass StackShield auch keine lokalen Variablen schützt.
-fstack-protector
:Dieser Mechanismus platziert einen canary vor dem EBP und reorganisiert lokale Variablen, um Puffer an höheren Speicheradressen zu positionieren, wodurch verhindert wird, dass sie andere Variablen überschreiben. Er kopiert auch sicher die Argumente, die auf dem Stack über lokalen Variablen übergeben werden, und verwendet diese Kopien als Argumente. Es schützt jedoch keine Arrays mit weniger als 8 Elementen oder Puffer innerhalb einer Benutzerstruktur.
Der canary ist eine Zufallszahl, die aus /dev/urandom
abgeleitet oder ein Standardwert von 0xff0a0000
ist. Er wird in TLS (Thread Local Storage) gespeichert, was es ermöglicht, dass gemeinsam genutzte Speicherbereiche über Threads hinweg thread-spezifische globale oder statische Variablen haben. Diese Variablen werden zunächst vom übergeordneten Prozess kopiert, und untergeordnete Prozesse können ihre Daten ändern, ohne den übergeordneten oder Geschwisterprozesse zu beeinflussen. Wenn jedoch ein fork()
ohne Erstellen eines neuen canary verwendet wird, teilen sich alle Prozesse (Eltern und Kinder) denselben canary, was ihn anfällig macht. Auf der i386-Architektur wird der canary bei gs:0x14
gespeichert, und auf x86_64 bei fs:0x28
.
Dieser lokale Schutz identifiziert Funktionen mit Puffern, die anfällig für Angriffe sind, und injiziert Code am Anfang dieser Funktionen, um den canary zu platzieren, und am Ende, um seine Integrität zu überprüfen.
Wenn ein Webserver fork()
verwendet, ermöglicht dies einen Brute-Force-Angriff, um das canary Byte für Byte zu erraten. Die Verwendung von execve()
nach fork()
überschreibt jedoch den Speicherbereich und negiert den Angriff. vfork()
ermöglicht es dem untergeordneten Prozess, ohne Duplikation auszuführen, bis er versucht zu schreiben, an welchem Punkt ein Duplikat erstellt wird, was einen anderen Ansatz zur Prozessgenerierung und Speicherverwaltung bietet.
In x64
-Binaries ist das canary-Cookie ein 0x8
Byte qword. Die ersten sieben Bytes sind zufällig und das letzte Byte ist ein null Byte.
In x86
-Binaries ist das canary-Cookie ein 0x4
Byte dword. Die ersten drei Bytes sind zufällig und das letzte Byte ist ein null Byte.
Das am wenigsten signifikante Byte beider canaries ist ein null Byte, da es das erste im Stack ist, das von niedrigeren Adressen kommt, und daher werden Funktionen, die Strings lesen, stoppen, bevor sie es lesen.
Leaking the canary und dann das Überschreiben (z.B. Pufferüberlauf) mit seinem eigenen Wert.
Wenn der canary in untergeordneten Prozessen geforkt wird, könnte es möglich sein, ihn byteweise zu brute-forcen:
Wenn es eine interessante Leck- oder willkürliche Leseanfälligkeit im Binary gibt, könnte es möglich sein, ihn zu leaken:
Überschreiben von im Stack gespeicherten Zeigern
Der Stack, der anfällig für einen Stacküberlauf ist, könnte Adressen zu Strings oder Funktionen enthalten, die überschrieben werden können, um die Anfälligkeit auszunutzen, ohne den Stack-Canary erreichen zu müssen. Überprüfen Sie:
Pointer RedirectingÄndern sowohl des Master- als auch des Thread-Canary
Ein Puffer Überlauf in einer threaded Funktion, die mit einem Canary geschützt ist, kann verwendet werden, um den Master-Canary des Threads zu ändern. Infolgedessen ist die Minderung nutzlos, da die Überprüfung mit zwei Canaries verwendet wird, die gleich sind (obwohl modifiziert).
Darüber hinaus könnte ein Puffer Überlauf in einer threaded Funktion, die mit einem Canary geschützt ist, verwendet werden, um den Master-Canary, der im TLS gespeichert ist, zu ändern. Dies liegt daran, dass es möglich sein könnte, die Speicherposition zu erreichen, an der das TLS gespeichert ist (und daher der canary) über einen bof im Stack eines Threads. Infolgedessen ist die Minderung nutzlos, da die Überprüfung mit zwei Canaries verwendet wird, die gleich sind (obwohl modifiziert). Dieser Angriff wird in dem Bericht durchgeführt: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
Überprüfen Sie auch die Präsentation von https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015, die erwähnt, dass normalerweise das TLS durch mmap
gespeichert wird und wenn ein Stack eines Threads erstellt wird, es auch durch mmap
generiert wird, was den Überlauf ermöglichen könnte, wie im vorherigen Bericht gezeigt.
Ändern des GOT-Eintrags von __stack_chk_fail
Wenn das Binary Partial RELRO hat, können Sie einen willkürlichen Schreibvorgang verwenden, um den GOT-Eintrag von __stack_chk_fail
in eine Dummy-Funktion zu ändern, die das Programm nicht blockiert, wenn der canary geändert wird.
Dieser Angriff wird in dem Bericht durchgeführt: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Lerne & übe GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)