# ヒープオーバーフロー {{#include ../../banners/hacktricks-training.md}} ## 基本情報 ヒープオーバーフローは[**スタックオーバーフロー**](../stack-overflow/index.html)のようなもので、ヒープ内で発生します。基本的には、ヒープ内にデータを格納するためのスペースが予約されており、**格納されたデータが予約されたスペースよりも大きいことを意味します。** スタックオーバーフローでは、命令ポインタやスタックフレームのようなレジスタがスタックから復元されることがわかっており、これを悪用することが可能です。ヒープオーバーフローの場合、**デフォルトではヒープチャンクに機密情報が格納されていません**が、機密情報やポインタが含まれる可能性があるため、**この脆弱性の重大性は**、**上書きされる可能性のあるデータ**と、攻撃者がこれをどのように悪用できるかに**依存します**。 > [!TIP] > オーバーフローオフセットを見つけるためには、[**スタックオーバーフロー**](../stack-overflow/index.html#finding-stack-overflows-offsets)と同じパターンを使用できます。 ### スタックオーバーフローとヒープオーバーフロー スタックオーバーフローでは、脆弱性がトリガーされる瞬間にスタックに存在するデータの配置がかなり信頼できます。これは、スタックが線形であり、常に衝突するメモリ内で増加し、**プログラムの実行中の特定の場所でスタックメモリは通常同様の種類のデータを格納し**、各関数によって使用されるスタック部分の末尾にいくつかのポインタがあるためです。 しかし、ヒープオーバーフローの場合、使用されるメモリは線形ではなく、**割り当てられたチャンクは通常メモリの別々の位置にあります**(隣接していない)し、**サイズによって割り当てを分けるためのビンやゾーン**があるため、**以前に解放されたメモリが新しいチャンクを割り当てる前に使用されます**。したがって、ヒープオーバーフローに対して脆弱なオブジェクトと衝突するオブジェクトを知るのは**複雑です**。そのため、ヒープオーバーフローが見つかった場合、**オーバーフローされるオブジェクトの隣に目的のオブジェクトを配置するための信頼できる方法を見つける必要があります**。 このために使用される技術の一つが**ヒープグルーミング**で、例えば[**この投稿**](https://azeria-labs.com/grooming-the-ios-kernel-heap/)で説明されています。この投稿では、iOSカーネルでゾーンがメモリを使い果たすと、カーネルページによって拡張され、このページが期待されるサイズのチャンクに分割され、順番に使用されることが説明されています(iOSバージョン9.2まで、その後はこれらのチャンクがランダム化された方法で使用され、攻撃の悪用を困難にします)。 したがって、ヒープオーバーフローが発生している前の投稿では、オーバーフローされたオブジェクトが被害者のオブジェクトと衝突するようにするために、**複数のスレッドによって複数の`kalloc`が強制され、すべての空きチャンクが埋められ、新しいページが作成されることを試みます**。 特定のサイズのオブジェクトでこの埋め込みを強制するために、**iOSマッチポートに関連するアウトオブライン割り当て**が理想的な候補です。メッセージのサイズを調整することで、`kalloc`割り当てのサイズを正確に指定でき、対応するマッチポートが破棄されると、対応する割り当ては即座に`kfree`に戻されます。 その後、これらのプレースホルダーのいくつかを**解放**できます。**`kalloc.4096`のフリーリストは、後入れ先出しの順序で要素を解放します**。これは基本的に、いくつかのプレースホルダーが解放され、エクスプロイトがオーバーフローに脆弱なオブジェクトを割り当てようとする際に、被害者オブジェクトがそのオブジェクトの後に続く可能性が高いことを意味します。 ### 例 libc [**このページ**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html)では、次のチャンクのprev in useビットとprevサイズの位置を上書きすることで、**使用中のチャンクを統合**(未使用だと思わせる)し、**再度割り当てる**ことができる基本的なヒープオーバーフローのエミュレーションを見つけることができます。 [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html)の別の例では、**ヒープオーバーフロー**を悪用して勝者関数を呼び出し、**フラグを取得する**非常に基本的なCTFの例が示されています。 [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html)の例では、バッファオーバーフローを悪用することで、**近くのチャンクにアドレスを上書きする**ことができ、**ユーザーからの任意のデータ**が書き込まれることがわかります。 ### 例 ARM64 ページ[https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/)では、実行されるコマンドがオーバーフローしたチャンクの次のチャンクに格納されるヒープオーバーフローの例を見つけることができます。したがって、次のような簡単なエクスプロイトで上書きすることで、実行されるコマンドを変更することが可能です。 ```bash python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt ``` ### 他の例 - [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/) - 整数オーバーフローの脆弱性を利用してヒープオーバーフローを引き起こします。 - オーバーフローしたチャンクの`struct`内の関数へのポインタを破損させ、`system`のような関数を設定してコード実行を得ます。 ### 実世界の例: CVE-2025-40597 – `__sprintf_chk`の誤用 SonicWall SMA100ファームウェア10.2.1.15では、リバースプロキシモジュール`mod_httprp.so`が**0x80バイト**のヒープチャンクを割り当て、その後`__sprintf_chk`を使用していくつかの文字列を連結します。 ```c char *buf = calloc(0x80, 1); /* … */ __sprintf_chk(buf, /* destination (0x80-byte chunk) */ -1, /* <-- size argument !!! */ 0, /* flags */ "%s%s%s%s", /* format */ "/", "https://", path, host); ``` `__sprintf_chk` は **_FORTIFY_SOURCE** の一部です。正の `size` パラメータを受け取ると、結果の文字列が宛先バッファに収まるかどうかを検証します。**`-1` (0xFFFFFFFFFFFFFFFF)** を渡すことで、開発者は実質的に **境界チェックを無効化** し、強化された呼び出しを古典的で安全でない `sprintf` に戻しました。 したがって、過度に長い **`Host:`** ヘッダーを提供することで、攻撃者は **0x80バイトのチャンクをオーバーフローさせ、次のヒープチャンクのメタデータを上書きする** ことができます(アロケータに応じて tcache / fast-bin / small-bin)。クラッシュは次のコマンドで再現できます: ```python import requests, warnings warnings.filterwarnings('ignore') requests.get( 'https://TARGET/__api__/', headers={'Host': 'A'*750}, verify=False ) ``` 実際のエクスプロイトには、制御可能なオブジェクトを脆弱なチャンクのすぐ後ろに配置するための**ヒープグルーミング**が必要ですが、根本的な原因は2つの重要なポイントを強調しています: 1. **_FORTIFY_SOURCEは万能ではない** – 誤用は保護を無効にする可能性があります。 2. 常に**正しいバッファサイズ**を`_chk`ファミリーに渡すこと(または、さらに良いことに、`snprintf`を使用すること)。 ## 参考文献 * [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/) {{#include ../../banners/hacktricks-training.md}}