【Heap応用編】Use-After-Free・Double Freeで世界を壊す|CTF思考フレームワーク #63
広告・PRを含みます。この記事にはアフィリエイトリンクが含まれます。掲載内容は編集方針に基づいて作成していますが、価格・在庫・キャンペーン内容はリンク先で最新情報を確認してください。

Use-After-Free と Double Free って、ヒープの典型バグだよね?🔁

そう。free したメモリを後から使う UAF、同じポインタを2回 free する Double Free。どちらも『ヒープのチェーンを攻撃者が操作できる』状態を作り、最終的に任意のアドレスを書き換える→RCE につながります。
Use-After-Free(UAF)と Double Free は、メモリ管理ミスから生じる脆弱性。OS・ブラウザ・Webアプリで毎年多数のCVEが発見されます。tcache poisoning、fastbin attack、large bin attack などの応用テクニックを組み合わせ、最終的に任意関数呼び出し・任意書込に至ります。

メモリ管理のミスがRCEまで繋がるって、ちょっと信じられない…
この記事は、CTF思考フレームワーク第63回。UAF・Double Free の仕組みと、tcache poisoning・fastbin attack の実装、CTF典型問題のパターン、現代glibc での攻略テクニックを整理します。
📖 この記事はシリーズの一部です
「CTF思考フレームワーク」 #63 / 全86記事 → シリーズ一覧を見る →
👻 解放した記憶領域をまだ使ってる、あるいは2回解放してしまう。Use-After-FreeとDouble Freeはヒープ攻撃の主役で、ブラウザ・カーネルexploitの長年の主戦場です。
UAFは「freeで返した領域に他の用途のオブジェクトが配置される」「古いポインタ経由でそのオブジェクトを書き換える」現象。Double Freeは同じ領域を2回freeしてbin構造を破壊する攻撃。tcacheの台頭で操作はずいぶん簡単に。
Use-After-Free・Double Freeで世界を壊します💀

UAFとDouble FreeはHeap攻撃の王道2大プリミティブ。組合せれば世界が壊せる💀
先に意味を押さえておくと読みやすい用語です。
- CTF: セキュリティの練習問題を解く競技。必ず許可された環境だけで試します。
- コンテナ: アプリを隔離された軽い実行環境で動かす仕組みです。
- Pwn: バイナリの不備を突いてプログラムの制御を奪うCTF分野です。
- ヒープ: プログラムが実行中に動的に使うメモリ領域です。
👀 観察フェーズ:まず何を見る?

まずアプリのfree後にポインタを使い続ける箇所がないか探す!イベント駆動・コールバック系が要注意🔍
対象アプリで「freeした後にポインタが残っていないか」「同じ領域を再利用していないか」「サイズが一致するオブジェクトが混在していないか」を確認。CTFバイナリでは構造体の混在が多用されます。
- free後にポインタをNULLにしているか
- 構造体同サイズの再mallocがあるか(コンテナ・ノート系問題)
- tcache key有無(glibc 2.32+)
- 関数ポインタ・vtable等の制御可能フィールド
- チャンクサイズ(fastbin/tcache範囲か)
- thread数(main_arena vs thread_arena)

C++のオブジェクト管理ミスでvtableハイジャックはブラウザ脆弱性の定番だね😨
🤔 仮説フェーズ:攻撃者は何を考える?

UAF/DF応用の4要素。
🕶️ 攻撃者は「freeで戻したチャンクが次のmallocでどこに行くか」を厳密に計画。UAFなら「同サイズで別構造体をmalloc → 古いポインタで書き換え → vtable / 関数ポインタを制御」、Double Freeなら「tcacheに同チャンクを2回入れて2回mallocさせる」のが定石。
🪦 仮説①:UAF→vtable hijack
C++オブジェクトをfree→同サイズallocで攻撃者データ配置→ぶら下がりポインタ経由でvtable呼出制御。
⚡ 仮説②:Double Free
同じchunkを2度free。tcache keyガードを回避するテクを組み合わせる。
🪤 仮説③:Type Confusion
異なる型を同じmemoryで使う。仮想関数テーブルの食い違いでRCE。
🛡️ 仮説④:safe-linking回避
glibc新版のfd ^ (chunk >> 12)難読化をheap baseリークで復元。

Heap応用は「メモリ再利用の予想と支配」がすべて💡
🔬 検証フェーズ:どうやって確かめる?

pwndbgのheap / vis_heap_chunksで解放と再allocの動きを可視化🧪
gdbのvis_heap_chunksでmalloc/free/再mallocの流れを追います。チャンクが「freeのbinに入る → 次のmallocで取り出される」順序を体感的に把握するのが学習の肝。
# UAFの典型シナリオ
# 1. malloc(0x40) → A(vtable付きオブジェクト)
# 2. free(A)(ただしポインタは残す)
# 3. malloc(0x40) → B(同サイズ・攻撃者制御の構造体)
# Bへの書き込みでAのvtableを上書き可能
# 4. AのvtableメソッドCallで任意関数実行
# Double Freeの典型
# free(p); free(p); → tcacheに同チャンク2回登録
# malloc, malloc → 同アドレスが2回返る
# → metadata操作の起点

実機検証はheap決定論的動作が必要だから、起動環境を揃えるのが大事💡
⚔️ 攻撃フェーズ:実際の手口

UAF/DF応用攻撃3パターン。
CTFでよく見る形:①ノート/タスクの「編集後にfreeしたが構造体ポインタを残す」→UAF、②free関数を2回呼ぶオプション→Double Free → Tcache Poisoning。最終的にvtable / __free_hook / __malloc_hookを書き換え。
# tcache double free → poisoning(glibc 2.27〜2.31)
malloc(0x40) # チャンクA確保
free(A)
free(A) # tcache double free(2.31までkey未導入で素通り)
# tcacheの単純連結リストで A→A の循環
malloc(0x40) # Aが返る
edit(A, target_addr) # fwdをtargetに書き換え
malloc(0x40) # Aが再び返る
malloc(0x40) # 次にtarget_addrがmallocで返る!
edit(target_addr, evil_value)
glibc 2.32以降は tcache key(mangle)でDouble Free検知が入りましたが、2.34まで __free_hook が削除されず使えてました。バージョン差は最重要⏳
C++オブジェクトのfreeとmalloc再使用でvtableに攻撃者ポインタ。ブラウザPwnの常套手段。
2度freeしたchunkでtcacheが偽chunkを参照→任意アドレスに割当。
glibc 2.34以降のFILE構造体悪用でhook無くしてもRCE。最新研究の主戦場。
🛡️ 防御フェーズ:どう守る?

Heap応用対策の3鉄則。
実装側の鉄則は「freeしたら必ずポインタをNULL」「ライフタイム管理を言語機能で担保」。AddressSanitizerは開発時の最強の武器。
- free直後にポインタをNULL代入
- C++ unique_ptr / shared_ptr
- AddressSanitizer (ASan)でテスト
- glibc 2.34+でtcache double free検知
- 長期的には Rust等メモリ安全言語へ
- fuzzer(AFL++/libFuzzer)で再現テスト
RustのownershipやGoのGCでUAF/DFが原理的に発生しない。
リリース前にAddressSanitizerを必ず通す。Fuzzerと組み合わせて潰す。
ブラウザのようにレンダラ分離。RCEが起きても被害を区画化。

Heap攻撃の「根絶は安全言語」「緩和はSandbox」の二段構え💪
🧪 pwn検証用のLinuxラボ
Pwnやエクスプロイトの練習は、必ず自分の検証環境で。💻 ConoHa VPSならLinuxをワンクリックで立てて、gdb-pedaやpwntoolsを仕込んでそのままトレーニングできます。
※ 上記は他社サービスへのリンクです。購入は各自でご判断ください。
⚠️ よくある落とし穴
- free直後のNULL代入を「不要な行」と削除
- tcache keyを「常に効いている」と誤認(2.31以下では効かない)
- Double Free検知を __free_hook 経由でバイパスされる事例を見落とす
- リファクタリング時にスマートポインタとraw pointerの混在
- thread arena・main arenaの違いで挙動が変わる場面
- ASanを「重いから本番性能テストで切る」
🧰 ツール早見表
| ツール | 用途 | 備考 |
|---|---|---|
| gdb + pwndbg | ヒープ可視化 | vis_heap_chunks/bins |
| ASan | 開発時のUAF/DF検出 | -fsanitize=address |
| Valgrind / Memcheck | メモリエラー検出 | 低速だが高精度 |
| how2heap | 攻撃手法カタログ | shellphish |
| glibc-all-in-one | バージョン切替 | CTF最適化 |
🎓 本気で学びたい人へ
ローレベルやOSレベルの許可を、仕事として深く学びたい方へ。🎓 ササエルはインフラとセキュリティの両方を学べるスクールです。
📚 もっと深く学びたい人へ
実際に手を動かして攻撃手法を体で覚えたいなら『7日間でハッキングをはじめる本 TryHackMe』がおすすめ📚
📚 次に読みたい
- Heap入門編|CTF思考フレームワーク #62
- Houseシリーズ編|CTF思考フレームワーク #64
- GOT・Format String編|CTF思考フレームワーク #61
- 保護機構と回避編|CTF思考フレームワーク #65
✍️ 学んだことを発信する
検証ノートをブログで公開したい方は、高速で安価なConoHa WINGが使いやすいです。
⚖️ 大事なお約束
この記事の手法は、必ず自分の環境か、許可されたCTF・脆弱性報奨金プログラム(HackerOne、Bugcrowd等)で試してください。他人のサービスに無断で攻撃を仕掛けるのは不正アクセス禁止法違反、立派な犯罪です。学んだ知識は守る側で活かしましょう🤝
この記事は合法な学習・防御目的での解説です。許可のないシステムへの攻撃は犯罪になります(不正アクセス禁止法ほか)。検証は必ず自分が管理する環境・CTF・公式ハンズオンで行ってください🙏



