ペネトレーションテスト&バグバウンティ
パソコンの中でプログラムは「メモリ」という場所を借りて作業しています。
使い終わったら「free(フリー)」して片づけるのがルールです。
でも…
「同じ場所を2回も片づける(freeする)」と大問題になるのです。
※イメージです。
ダブルフリーとは
ダブルフリー(double free )とは、同じメモリ領域を2回以上解放(free())してしまうことです。
C言語やC++でヒープメモリを扱うときに、解放ミスがあるとこの脆弱性が発生します。
これにより、プログラムのクラッシュやメモリの乗っ取りといった深刻なセキュリティ問題を引き起こす可能性があります。
ダブルフリーの発生原因とは
発生する主な原因は以下の通りです。
・free()したあとにポインタを NULL にしなかった。
・同じポインタを別の変数に代入し、両方で free()。
・if 分岐などのロジックミスで同じポインタを2回解放。
C言語の簡単な例で理解しよう
1.プログラム
ファイル名はたとえば double_free.c にします。
nano double_free.c
下記のコードを貼り付けて、Ctrl + O → Enter → Ctrl + X で保存します。
#include <stdlib.h>
int main() {
char *ptr = malloc(32);
free(ptr);
free(ptr); // ← 2回目の解放(バグ)
return 0;
}
このコードは、実行するとクラッシュ(double free or corruption)する可能性があります。
2.コンパイル
gcc -o double_free double_free.c -no-pie -fno-stack-protector
3.実行します。
./double_free
※エラーの内容
・free(): double free detected in tcache 2
tcache(Thread Cache)は、glibc 2.26以降のmalloc()の高速化のためのメモリ管理機構です。
「同じポインタを2回、freeした」ことが検出され、危険な操作だと判断されてプログラムを停止します。
tcache 2は、特定のサイズに対応するキャッシュのスロットを意味します。
・zsh: IOT instruction ./double_free
IOT instruction(Interrupt On Trap)は、意図的にプログラムを停止させるための信号(SIGABRT)です。
glibcが「異常なfree」と判断して、abort()関数を呼び出して異常終了させたという意味です。
悪用されるパターンとは
ヒープ管理には「tcache」というキャッシュ構造があり、これを利用することでメモリ操作を乗っ取り、最終的には任意のコードを実行できてしまいます。
攻撃者は、2回目の free() を悪用して「tcacheのリンク情報」を改ざんし、malloc()で好きな場所のアドレスを得ることができます(tcache poisoning)。
実際にどう攻撃されるのか
1回目の free():正しく解放 → tcacheに保存。
2回目の free():同じアドレスが2重に tcache に入る。
次の malloc():攻撃者が書き換えたアドレスが返ってくる。
→ 任意のメモリに malloc()でアクセスできる。(任意書き込み)
このようにして、関数ポインタや GOT などを改ざんできる可能性があるのです。
対策方法
安全にメモリを扱うには。
・free()したら、ポインタをNULLにする。
・同じポインタを複数の変数で管理しない。
・静的解析ツール(like clang-analyzer)でチェック。
・C++ならスマートポインタを使う。
ハッカーが利用するダブルフリーとは? 同じメモリを2回解放する危険な落とし穴のまとめ
ダブルフリー(Double Free)とは、同じメモリ領域を2回以上 free() で解放してしまう危険なバグです。本来、一度解放されたメモリを再び解放すると、メモリ管理が壊れてしまい、予期せぬ動作やプログラムのクラッシュにつながります。攻撃者はこの脆弱性を利用して、任意のメモリ領域にアクセスしたり、プログラムの動作を乗っ取ったりする可能性があります。特にLinuxでは、tcacheという高速化機構が使われており、この仕組みを悪用した「tcache poisoning」という攻撃手法も存在します。対策としては、free()後にポインタをNULLにする、メモリの管理を整理するなどが重要です。
セキュアなプログラミングを身につけるには、こうした脆弱性の仕組みと対策を理解しておくことが大切です。