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

【Houseシリーズ編】House of Force・Spiritでヒープを乗っ取る|CTF思考フレームワーク #64

かも次郎とアンペンが「Houseシリーズ」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

今回はHouseシリーズ──glibcヒープ攻撃の名門技集です。2007年Phrack 67号「Malloc Maleficarum」でPhantasmal Phantasmagoria氏が体系化したのが起源で、その後の研究者が新技を発見するたびに「House of ◯◯」と命名されてきた歴史があります。CTF Heap問題ではこれらの名前が共通語彙として飛び交うので、それぞれの『発想の核』を押さえておくと一気に読みやすくなります。

共通点は『malloc/freeのアルゴリズム仕様の隙を突いて、freeリストや内部メタデータを操る』こと。glibcバージョンごとに使える技が消滅したり新生したりするので、『どの技がどのバージョンで生きているか』のマッピングが実戦の鍵です。

『House of なんとか』がいくつも出てくると、それだけで身構えてしまいますよね。でも安心してください。これらは“流派の名前”のようなものです。剣術に流派があるように、ヒープ攻撃にも『この隙はこう突く』という名のついた型があるだけ。全部を暗記する必要はなく、『どの型が、ヒープのどの部分を狙うのか』という“地図”を持っておけば、CTFの解説を読むときに迷子になりません。

『House of 〇〇』って名前がいっぱいあるけど、関係あるの?

全部『malloc仕様の別々の隙』を突く独立した技。Force=top chunk弄り、Spirit=偽チャンク作成、Lore=small bin改竄、Orange=unsorted bin attack。条件と前提が違うから、問題に応じて使い分けになるよ。

まず結論

Houseシリーズの代表4種:(1)House of Force(top chunkのsizeをBoFで巨大化→巨大malloc要求で任意アドレスを切り出す/glibc 2.29で殺された)、(2)House of Spirit(スタック等に偽チャンクヘッダを作りfreeしてtcache/fastbinに食わせる)、(3)House of Lore(small binの双方向リストを偽造して任意malloc)、(4)House of Orange(top chunkの整理に乗じてunsorted bin attack→任意書込)。現代の主流はIO_FILE系(_IO_2_1_stdout_のvtable改竄)とHouse of Rust。glibcバージョンと技の対応を常に確認。

この記事で分かること

  • Houseシリーズの全体像と歴史的背景
  • 主要4種(Force/Spirit/Lore/Orange)の発想の核
  • glibcバージョン進化と各技の生死マップ
  • 現代版(IO_FILE系/House of Rust)への入口
  • 守る側の選択肢(新glibc+メモリ安全言語+Hardened allocator)
難易度:上級 所要時間:13分 体験:how2heapで各種試行 おすすめ:#63の後

📖 はじめてのWebセキュリティ #64|Houseシリーズ編
House of Force・Spiritでヒープを乗っ取る。 シリーズ一覧を見る →

⚠️ 大事なお約束
本番システムへのexploitは違法。CTF・自作バイナリ・how2heap等の検証環境のみで確認してください。

主要House 4種の発想を比べる

それぞれが攻めるglibc構造

  • House of Force:ヒープ末尾のtop chunksizeフィールドをBoFで0xFFFFFFFFFFFFFFFF等に書き換え→巨大mallocを要求すると『要求量だけtopから切り出して残りを新topにする』処理が攻撃者制御の場所に新topを置く。glibc 2.29で size validate が入り無効化
  • House of Spirit:stack上やbss上に偽のチャンクヘッダを仕込み、そのアドレスをfree()するとtcache/fastbinが受け入れる。続くmallocが偽チャンク領域を返す。サイズ整合性の検証を回避できる時に有効
  • House of Lore:small binの双方向リスト(bk/fd)を偽造。victim->bk = fake_chunk_addrと書き込みmallocを誘導すると、fake_chunkが返却される。unlinkマクロのチェックを通る形に偽装する必要
  • House of Orange:top chunkを使い切るような巨大mallocを誘発するとtopがunsorted binへ送られる。そこでunsorted bin attack(victim->bk = target - 0x10)でtargetmain_arenaのアドレスを書く。元はFile Stream(_IO_FILE)を狙うHouse of Orange exploitの構成要素
  • House of Rust(現代): glibc 2.32+のSafe-Linking対応。tcache poisoningを暗号化されたfdに対応させた最新版。ヒープベースを別経路でリーク後にXOR解除して仕込む

4つを一言で覚えるなら、『どこを攻めるか』で区別するのがコツです。Forceはヒープの“末尾の空き地(top chunk)”、Spiritは“偽の表札(偽チャンク)”、Loreは“住人名簿(双方向リスト)”、Orangeは“大工事のドサクサ(unsorted bin)”。狙う場所がそれぞれ違うから、使える前提条件も違います。問題を見て『今いじれるのはどこか』を考えると、自然と使う型が絞れてきますよ。

House of Force・Spirit・Lore・Orangeの4つのHouseシリーズ攻撃を2x2グリッドで示した図解
図1:Houseシリーズ主要4種(Force/Spirit/Lore/Orange)
🏠 たとえるなら、家ごとに異なる侵入の流儀

同じ通りに並ぶ4軒の家でも、それぞれ違う流儀で侵入されます。『House of Force』は屋根の高さ表示を書き換えて家を巨大化させ、別の敷地まで自分の家ということにする流儀。『House of Spirit』は偽の表札を立てて別の家のフリをして郵便を受け取る流儀。『House of Lore』は町内会の住人名簿(双方向リスト)を改竄して別人を住人として登録する流儀。『House of Orange』は大規模工事の段取りに乗じて公文書を書き換える流儀。家の構造(glibcの仕様)の細かい癖を、それぞれ別の角度から突く特殊技です。

ここで覚える用語:top chunk / unsorted bin attack
top chunkはヒープ末尾の『まだ誰にも割り当てられていない最大の空き領域』。新規mallocはまずtopから切り出されます。多くのHouse技がここを操作します。unsorted bin attackは『freeチャンクのbkを書き換えてmallocを呼ぶと、attacker指定のtargetアドレスにmain_arena内のあるアドレスが書き込まれる』性質を悪用するプリミティブ。任意リーク・任意書込の入口として、現代でも様々なexploitに組み込まれます。

glibc進化との追いかけっこ

House技はglibcバージョンに激しく依存します。攻撃者が新技を発見→glibcメンテナが検証チェックを追加→無効化→別の隙が見つかり新技誕生……という追いかけっこが20年続いています。下記が主要な節目。

この“追いかけっこ”、傍から見るとちょっとワクワクします。攻撃者が新しい隙を見つけるたび、glibcの開発者が見張りを足して塞ぎ、するとまた別の隙が見つかる——20年続く知恵比べです。だから実戦では『相手のglibcが何年世代か』を真っ先に確認するのが鉄則。同じ技でも、世代が1つ違うだけで通ったり弾かれたりします。“いつの時代の家か”を知ってから、侵入の流儀を選ぶわけです。

  • glibc 2.26(2017): tcache導入。tcache poisoningの時代が始まる
  • glibc 2.29(2019): tcache_entry.keyでdouble-free検出+top chunkのsize validate → House of Force殺し
  • glibc 2.32(2020): Safe-Linking(fdをheap上位ビットでXOR保護) → tcache/fastbin poisoning難化
  • glibc 2.34(2021): __free_hook / __malloc_hook 削除 → 旧攻撃経路封鎖
  • 2022〜現代: _IO_2_1_stdout_ / _IO_FILE vtable直接書換、House of Rust等が主流
glibc 2.26から2.34までのバージョン進化とHouse技の有効性変遷タイムライン図解
図3:glibcバージョンによってHouse技の有効性は変わる
4軒の家にそれぞれ違うスタイルの侵入者が現れるHouseシリーズのたとえイラスト
図2:家ごとに違う流儀の侵入=Houseシリーズ

CTFでやってみよう:how2heapで実機検証

やってみよう / 自分の環境・CTFのみ

shellphish/how2heap で複数House技を動かす

目的は『各House技がglibcバージョンによって動く/動かない』を実機で確認することです。バージョン差を体感すると、CTF本番でldd --versionを最初に叩く癖が付きます。

  1. git clone https://github.com/shellphish/how2heap.git
  2. ldd --version で自分のglibcバージョンを確認(例:2.35)
  3. 該当フォルダ(glibc_2.35/)に移動→lsで動くサンプル一覧を確認
  4. make house_of_einherjar 等をビルド→実行→printf出力で『stack上の変数を返したぞ!』を見る
  5. gdb+pwndbgでheap chunks/bins/tcachebinsを実行、binの内部状態を観察
  6. 2.27/2.31の古いフォルダにあるサンプルを2.35環境で実行→失敗することを確認(検証強化が効いている証拠)
  7. 余裕があればhouse_of_kibana等の最新版に挑戦、IO_FILE系の世界へ
本番環境・他者バイナリへの適用厳禁。検証はCTF・how2heap・自作バイナリで。VMまたはコンテナを使うと安全。

守る側:『新glibc+メモリ安全言語+確率的検出』

古典ヒープ攻撃への対策
  • glibcは常に最新(ディストリのstable+セキュリティパッチ即適用)。古いLTSを長く使う場合はCVE追跡を必須化
  • C/C++を続けるならASan+UBSanを開発・CIで強制。本番では性能影響を考えてGWP-ASan(確率的)
  • 新規プロダクトはRustで書く(所有権モデルがUAF/Double Freeを構文的に拒否、Houseシリーズ前提の脆弱性ごと排除)
  • 本番ではHardened allocator(Scudo(Android標準), jemallocセキュア設定, mimalloc-secure)を採用
  • 監視で同一プロセスのheap関連クラッシュを異常検知としてフラグ化、自動exploitの早期発見
  • カーネルならKASANを有効化し、ヒープバグを開発段階で潰す
  • サプライチェーン(依存ライブラリ)も同じく最新化、CVE-2024-XXX等のヒープバグ修正を怠らない

House系は『glibcとの追いかけっこ』なんだね…バージョン確認が最初の一手か。

次回は保護機構と回避。Canary・PIE・ASLR・RELROの仕組みと、それぞれの突破口を整理するよ。

まとめ:『glibcバージョン×技のマッピング』が実戦の鍵

今回のポイント
  • Houseシリーズはmalloc/free仕様の隙を個別に突く独立技の集合
  • 主要4種:Force / Spirit / Lore / Orange+現代版IO_FILE / Rust
  • glibcバージョン依存→ldd --version確認が初手
  • 守りは最新glibc + メモリ安全言語 + Hardened allocator + ASan/Fuzz

今日の持ち帰りは『Houseシリーズは“暗記”ではなく“地図”で捉える』。それぞれが狙うヒープの部位と、効くglibc世代さえ押さえておけば、初見の型でも『ああ、あの場所を別角度から突いているのか』と読み解けます。攻防はバージョンとともに動き続ける——その前提を忘れないことが、いちばんの武器になります。

次回は保護機構と回避編。Canary・PIE・ASLR・RELROの内部と、それぞれの突破口・新世代CET等まで整理します。

次に読みたい記事

参考資料

記事URLをコピーしました