PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。

【Heap応用編】Use-After-Free・Double Freeで世界を壊す|CTF思考フレームワーク #63

【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)

UAFはfree後にぶら下がりポインタからアクセス。再allocで攻撃者制御データが置かれるとvtable書換へ繋がります👀

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 が削除されず使えてました。バージョン差は最重要⏳

① UAF→任意関数呼出

C++オブジェクトのfreeとmalloc再使用でvtableに攻撃者ポインタ。ブラウザPwnの常套手段。

② Double Free→任意malloc配置

2度freeしたchunkでtcacheが偽chunkを参照→任意アドレスに割当。

③ House of Apple/Botcake

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が原理的に発生しない。

🛡️ HWASan/ASan常用

リリース前にAddressSanitizerを必ず通す。Fuzzerと組み合わせて潰す。

🧱 Sandboxとプロセス分離

ブラウザのようにレンダラ分離。RCEが起きても被害を区画化。

Heap攻撃の「根絶は安全言語」「緩和はSandbox」の二段構え💪

🧪 pwn検証用のLinuxラボ

Pwnやエクスプロイトの練習は、必ず自分の検証環境で。💻 ConoHa VPSならLinuxをワンクリックで立てて、gdb-pedaやpwntoolsを仕込んでそのままトレーニングできます。

PR / 広告

ConoHa VPS

※ 上記は他社サービスへのリンクです。購入は各自でご判断ください。

⚠️ よくある落とし穴

  1. free直後のNULL代入を「不要な行」と削除
  2. tcache keyを「常に効いている」と誤認(2.31以下では効かない)
  3. Double Free検知を __free_hook 経由でバイパスされる事例を見落とす
  4. リファクタリング時にスマートポインタとraw pointerの混在
  5. thread arena・main arenaの違いで挙動が変わる場面
  6. ASanを「重いから本番性能テストで切る」

🧰 ツール早見表

ツール用途備考
gdb + pwndbgヒープ可視化vis_heap_chunks/bins
ASan開発時のUAF/DF検出-fsanitize=address
Valgrind / Memcheckメモリエラー検出低速だが高精度
how2heap攻撃手法カタログshellphish
glibc-all-in-oneバージョン切替CTF最適化

🎓 本気で学びたい人へ

ローレベルやOSレベルの許可を、仕事として深く学びたい方へ。🎓 ササエルはインフラとセキュリティの両方を学べるスクールです。

PR / 広告

ササエル

📚 もっと深く学びたい人へ

実際に手を動かして攻撃手法を体で覚えたいなら『7日間でハッキングをはじめる本 TryHackMe』がおすすめ📚

📚 次に読みたい

✍️ 学んだことを発信する

検証ノートをブログで公開したい方は、高速で安価なConoHa WINGが使いやすいです。

PR / 広告

ConoHa WING

⚖️ 大事なお約束

必ず守ってね

この記事の手法は、必ず自分の環境か、許可されたCTF・脆弱性報奨金プログラム(HackerOne、Bugcrowd等)で試してください。他人のサービスに無断で攻撃を仕掛けるのは不正アクセス禁止法違反、立派な犯罪です。学んだ知識は守る側で活かしましょう🤝

この記事は合法な学習・防御目的での解説です。許可のないシステムへの攻撃は犯罪になります(不正アクセス禁止法ほか)。検証は必ず自分が管理する環境・CTF・公式ハンズオンで行ってください🙏

記事URLをコピーしました