8.1 KiB
ダブルフリー
{% hint style="success" %}
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 DiscordグループまたはTelegramグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
基本情報
メモリブロックを複数回解放すると、アロケータのデータが混乱し、攻撃の扉が開かれる可能性があります。これは次のように発生します:メモリブロックを解放すると、それはフリーチャンクのリスト(例えば、「ファストビン」)に戻ります。同じブロックを連続して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つのポインタを通じてデータを操作すると、他のポインタにも影響を与え、重大なセキュリティリスクと悪用の可能性を生み出します。
実行すると、i1
とi2
が同じアドレスを取得したことに注意してください:
初期割り当て:
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
例
- Dragon Army. Hack The Box
- サイズ
0x70
を除いて、ファストビンサイズのチャンクしか割り当てられず、通常の__malloc_hook
の上書きを防ぎます。 - 代わりに、
0x56
で始まるPIEアドレスをファストビンの重複のターゲットとして使用します(1/2の確率)。 - PIEアドレスが格納される場所の1つは
main_arena
で、これはGlibc内にあり、__malloc_hook
の近くにあります。 - 特定のオフセットの
main_arena
をターゲットにして、そこにチャンクを割り当て、__malloc_hook
に到達するまでチャンクを割り当て続けてコード実行を取得します。 - zero_to_hero. PicoCTF
- Tcacheビンとヌルバイトオーバーフローを使用して、ダブルフリーの状況を達成できます:
- サイズ
0x110
のチャンクを3つ(A
、B
、C
)割り当てます。 B
を解放します。A
を解放し、ヌルバイトオーバーフローを使用するために再度割り当てます。- 現在、
B
のサイズフィールドは0x100
であり、0x111
ではないため、再度解放できます。 - サイズ
0x110
のTcacheビンとサイズ0x100
のTcacheビンが同じアドレスを指しています。したがって、ダブルフリーがあります。 - Tcache poisoningを使用してダブルフリーを利用します。
参考文献
{% hint style="success" %}
AWSハッキングを学び、練習する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、練習する:HackTricks Training GCP Red Team Expert (GRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。