Double Free

Reading time: 5 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks

Grundinformationen

Wenn Sie einen Speicherblock mehr als einmal freigeben, kann dies die Daten des Allocators durcheinanderbringen und die Tür zu Angriffen öffnen. So passiert es: Wenn Sie einen Speicherblock freigeben, geht er zurück in eine Liste freier Blöcke (z. B. den "fast bin"). Wenn Sie denselben Block zweimal hintereinander freigeben, erkennt der Allocator dies und gibt einen Fehler aus. Aber wenn Sie dazwischen einen anderen Block freigeben, wird die Überprüfung auf doppelte Freigabe umgangen, was zu einer Beschädigung führt.

Wenn Sie jetzt neuen Speicher anfordern (mit malloc), könnte der Allocator Ihnen einen Block geben, der zweimal freigegeben wurde. Dies kann dazu führen, dass zwei verschiedene Zeiger auf denselben Speicherort zeigen. Wenn ein Angreifer einen dieser Zeiger kontrolliert, kann er den Inhalt dieses Speichers ändern, was zu Sicherheitsproblemen führen oder ihm sogar ermöglichen kann, Code auszuführen.

Beispiel:

c
#include <stdio.h>
#include <stdlib.h>

int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);

// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);

// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);

// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);


// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);

// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);

return 0;
}

In diesem Beispiel, nachdem der Tcache mit mehreren freigegebenen Chunks (7) gefüllt wurde, wird Chunk h freigegeben, dann Chunk i und dann h erneut, was zu einem Double Free führt (auch bekannt als Fast Bin dup). Dies eröffnet die Möglichkeit, überlappende Speicheradressen bei der Reallokation zu erhalten, was bedeutet, dass zwei oder mehr Zeiger auf denselben Speicherort zeigen können. Das Manipulieren von Daten über einen Zeiger kann dann den anderen beeinflussen, was ein kritisches Sicherheitsrisiko und Potenzial für Ausnutzung schafft.

Bei der Ausführung, beachten Sie, wie i1 und i2 die gleiche Adresse erhalten haben:

Initial allocations:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
After reallocations:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0

Beispiele

  • Dragon Army. Hack The Box
  • Wir können nur Fast-Bin-große Chunks außer für die Größe 0x70 zuweisen, was das übliche __malloc_hook Überschreiben verhindert.
  • Stattdessen verwenden wir PIE-Adressen, die mit 0x56 beginnen, als Ziel für Fast Bin dup (1/2 Chance).
  • Ein Ort, an dem PIE-Adressen gespeichert sind, ist in main_arena, das sich innerhalb von Glibc und in der Nähe von __malloc_hook befindet.
  • Wir zielen auf einen bestimmten Offset von main_arena, um dort einen Chunk zuzuweisen und weiterhin Chunks zuzuweisen, bis wir __malloc_hook erreichen, um Codeausführung zu erhalten.
  • zero_to_hero. PicoCTF
  • Mit Tcache-Bins und einem Null-Byte-Overflow können wir eine Double-Free-Situation erreichen:
  • Wir weisen drei Chunks der Größe 0x110 zu (A, B, C)
  • Wir geben B frei
  • Wir geben A frei und weisen erneut zu, um den Null-Byte-Overflow zu nutzen
  • Jetzt ist das Größenfeld von B 0x100, anstatt 0x111, sodass wir es erneut freigeben können
  • Wir haben einen Tcache-Bin der Größe 0x110 und einen der Größe 0x100, die auf dieselbe Adresse zeigen. Also haben wir einen Double Free.
  • Wir nutzen den Double Free mit Tcache poisoning

Referenzen

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks