hacktricks/src/binary-exploitation/libc-heap/off-by-one-overflow.md

114 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Off by one overflow
{{#include ../../banners/hacktricks-training.md}}
## 基本情報
1Bのオーバーフローにアクセスすることで、攻撃者は次のチャンクの`size`フィールドを変更できます。これにより、実際に解放されるチャンクを改ざんでき、別の正当なチャンクを含むチャンクを生成する可能性があります。このエクスプロイトは[ダブルフリー](double-free.md)やオーバーラップチャンクに似ています。
オフバイワンの脆弱性には2種類あります
- 任意のバイト:このタイプは、そのバイトを任意の値で上書きすることを可能にします
- ヌルバイトオフバイヌルこのタイプは、そのバイトを0x00でのみ上書きすることを可能にします
- この脆弱性の一般的な例は、`strlen``strcpy`の動作が不一致である以下のコードに見られ、次のチャンクの先頭に0x00バイトを設定できることです。
- これは[エインヘリヤルの家](house-of-einherjar.md)を使ってエクスプロイトできます。
- Tcacheを使用している場合、これは[ダブルフリー](double-free.md)の状況に利用できます。
<details>
<summary>オフバイヌル</summary>
```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}
```
</details>
他のチェックの中で、現在、チャンクが解放されるたびに、前のサイズがメタデータのチャンクに設定されたサイズと比較されるため、この攻撃はバージョン2.28からかなり複雑になっています。
### コード例:
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
- この攻撃はTcachesの使用によりもはや機能しません。
- さらに、より大きなチャンクを使用して悪用しようとするとtcachesが関与しないように、次のエラーが発生します: `malloc(): invalid next size (unsorted)`
### 目標
- チャンクが別のチャンクの中に含まれるようにし、その2番目のチャンクへの書き込みアクセスが含まれているチャンクを上書きできるようにする
### 要件
- サイズメタデータ情報を変更するためのオフバイワンオーバーフロー
### 一般的なオフバイワン攻撃
- チャンク `A``B``C`サイズ0x20と仮定を3つ割り当て、トップチャンクとの統合を防ぐためにもう1つを割り当てます。
- `C`を解放します0x20 Tcacheフリーリストに挿入されます
- チャンク `A`を使用して`B`にオーバーフローします。オフバイワンを悪用して、`B``size`フィールドを0x21から0x41に変更します。
- これで、`B`が解放されたチャンク`C`を含むようになります。
- `B`を解放し、0x40チャンクを割り当てます再びここに配置されます
- まだ解放されている`C``fd`ポインタを変更できますTcacheポイズニング
### オフバイヌル攻撃
- メモリの3つのチャンクa、b、cが順番に予約されます。次に、中間のチャンクが解放されます。最初のチャンクにはオフバイワンオーバーフローの脆弱性があり、攻撃者は0x00を使用して悪用します前のバイトが0x10だった場合、中間のチャンクは実際よりも0x10小さいことを示します
- 次に、中間の解放されたチャンクbに2つの小さなチャンクが割り当てられますが、`b + b->size`は、指されているアドレスが必要なサイズよりも小さいため、チャンクcを更新しません。
- 次に、b1とcが解放されます。`c - c->prev_size`はまだb現在はb1を指しているため、両方が1つのチャンクに統合されます。しかし、b2はまだb1とcの間にあります。
- 最後に、新しいmallocが実行され、このメモリ領域を再利用します。実際にはb2を含むことになり、新しいmallocの所有者がb2の内容を制御できるようになります。
この画像は攻撃を完璧に説明しています:
<figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure>
## その他の例と参考文献
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
- `strlen`が次のチャンクの`size`フィールドを考慮するため、オフバイワン。
- Tcacheが使用されているため、一般的なオフバイワン攻撃がTcacheポイズニングを使用して任意の書き込みプリミティブを取得するのに機能します。
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
- オフバイワンを悪用してヒープからアドレスを漏洩させることが可能です。これは、文字列の終わりのバイト0x00が次のフィールドによって上書きされるためです。
- 任意の書き込みは、オフバイワンの書き込みを悪用してポインタを別の場所に指すようにし、そこに偽の構造体と偽のポインタを構築します。次に、この構造体のポインタをたどって任意の書き込みを取得できます。
- libcアドレスが漏洩するのは、ヒープがmmapを使用して拡張されると、mmapによって割り当てられたメモリがlibcから固定オフセットを持つためです。
- 最後に、任意の書き込みが悪用され、__free_hookのアドレスにone gadgetが書き込まれます。
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
- ユーザー入力行を読み取る`getline`関数にNULLオフバイワンの脆弱性があります。この関数は、コンテンツの「キー」を読み取るために使用され、コンテンツ自体ではありません。
- 書き込みには最初に5つのチャンクが作成されます
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- チャンク防御 (0x400) はトップチャンクとの統合を避けるためのものです。
- 次に、チャンク1、5、3が解放されるので
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- 次に、チャンク3 (0x1f8)を悪用して、nullオフバイワンがprev_sizeを`0x4e0`に書き込みます。
- 最初に割り当てられたチャンク1、2、5、3のサイズとそれらのチャンクのヘッダーの合計が`0x4e0`に等しいことに注意してください:`hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- 次に、チャンク4が解放され、すべてのチャンクを消費するチャンクが生成されます
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
```
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- 次に、`0x200`バイトが割り当てられ、元のチャンク1が埋められます。
- そして、別の0x200バイトが割り当てられ、チャンク2が破壊され、したがって漏洩は発生せず、これは機能しませんかおそらく、これは行うべきではありません。
- 次に、0x58の"a"で別のチャンクが割り当てられチャンク2を上書きし、チャンク5に到達、チャンク5のファストビンチャンクの`fd`を`__malloc_hook`を指すように変更します。
- 次に、0x68のチャンクが割り当てられ、`__malloc_hook`の偽のファストビンチャンクが次のファストビンチャンクになります。
- 最後に、0x68の新しいファストビンチャンクが割り当てられ、`__malloc_hook`が`one_gadget`アドレスで上書きされます。
{{#include ../../banners/hacktricks-training.md}}