Double Free

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)

HackTricksをサポートする

基本情報

メモリブロックを複数回解放すると、アロケータのデータが混乱し、攻撃の扉が開かれる可能性があります。これは次のように発生します:メモリブロックを解放すると、それはフリーチャンクのリスト(例えば、「ファストビン」)に戻ります。同じブロックを連続して2回解放すると、アロケータはこれを検出し、エラーをスローします。しかし、その間に別のチャンクを解放すると、ダブルフリーのチェックがバイパスされ、破損が発生します。

さて、新しいメモリを要求すると(mallocを使用)、アロケータは2回解放されたブロックを提供する可能性があります。これにより、2つの異なるポインタが同じメモリ位置を指すことになります。攻撃者がそのポインタの1つを制御している場合、彼らはそのメモリの内容を変更でき、これがセキュリティ問題を引き起こしたり、コードを実行させることを可能にしたりします。

例:

#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;
}

この例では、tcacheをいくつかの解放されたチャンク(7)で埋めた後、コードはチャンクhを解放し、次にチャンクiを解放し、再びhを解放することでダブルフリーを引き起こします(ファストビンの重複とも呼ばれます)。これにより、再割り当て時に重複するメモリアドレスを受け取る可能性が生じ、2つ以上のポインタが同じメモリ位置を指すことができます。1つのポインタを通じてデータを操作すると、他のポインタにも影響を与え、重大なセキュリティリスクと悪用の可能性を生み出します。

実行すると、i1i2が同じアドレスを取得したことに注意してください

初期割り当て:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
再割り当て後:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0

  • サイズ0x70を除いて、ファストビンサイズのチャンクしか割り当てられず、通常の__malloc_hookの上書きを防ぎます。

  • 代わりに、0x56で始まるPIEアドレスをファストビンの重複のターゲットとして使用します(1/2の確率)。

  • PIEアドレスが格納される場所の1つはmain_arenaで、これはGlibc内にあり、__malloc_hookの近くにあります。

  • 特定のオフセットのmain_arenaをターゲットにして、そこにチャンクを割り当て、__malloc_hookに到達するまでチャンクを割り当て続けてコード実行を取得します。

  • Tcacheビンとヌルバイトオーバーフローを使用して、ダブルフリーの状況を達成できます:

  • サイズ0x110のチャンクを3つ(ABC)割り当てます。

  • Bを解放します。

  • Aを解放し、ヌルバイトオーバーフローを使用するために再度割り当てます。

  • 現在、Bのサイズフィールドは0x100であり、0x111ではないため、再度解放できます。

  • サイズ0x110のTcacheビンとサイズ0x100のTcacheビンが同じアドレスを指しています。したがって、ダブルフリーがあります。

  • Tcache poisoningを使用してダブルフリーを利用します。

参考文献

AWSハッキングを学び、練習する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、練習する:HackTricks Training GCP Red Team Expert (GRTE)

HackTricksをサポートする

Last updated