Off by one overflow
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
1Bオーバーフローへのアクセスがあると、攻撃者は次のチャンクのsize
フィールドを変更できます。これにより、実際に解放されるチャンクを改ざんでき、別の正当なチャンクを含むチャンクを生成する可能性があります。この脆弱性の悪用は、ダブルフリーやオーバーラップチャンクに似ています。
オフバイワン脆弱性には2種類あります:
任意のバイト:この種類は、そのバイトを任意の値で上書きすることを可能にします。
ヌルバイト(オフバイヌル):この種類は、そのバイトを0x00でのみ上書きすることを可能にします。
この脆弱性の一般的な例は、strlen
とstrcpy
の動作が不一致である以下のコードに見られ、次のチャンクの先頭に0x00バイトを設定できることを示しています。
これはエインヘリャルの家を使って悪用できます。
Tcacheを使用している場合、これはダブルフリーの状況に利用できます。
他のチェックの中で、チャンクが解放されるたびに、前のサイズがメタデータのチャンクに設定されたサイズと比較されるため、この攻撃はバージョン2.28以降かなり複雑になっています。
この攻撃はTcachesの使用によりもはや機能しません。
さらに、より大きなチャンクを使用して悪用しようとすると(tcachesが関与しないため)、次のエラーが発生します: malloc(): invalid next size (unsorted)
チャンクが別のチャンクの中に含まれるようにし、その2番目のチャンクへの書き込みアクセスにより、含まれているチャンクを上書きできるようにする
サイズメタデータ情報を変更するためのオフバイワンオーバーフロー
チャンク A
、B
、C
(サイズ0x20とする)を3つ割り当て、トップチャンクとの統合を防ぐために別のチャンクを割り当てます。
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の内容を制御できるようになります。
この画像は攻撃を完璧に説明しています:
strlen
が次のチャンクのsize
フィールドを考慮するためのオフバイワン。
Tcacheが使用されているため、一般的なオフバイワン攻撃がTcacheポイズニングを使用して任意の書き込みプリミティブを取得するために機能します。
オフバイワンを悪用してヒープからアドレスを漏洩させることが可能です。これは、次のフィールドによって上書きされる文字列の終わりのバイト0x00によるものです。
任意の書き込みは、オフバイワンの書き込みを悪用してポインタを別の場所に指すようにし、そこに偽の構造体と偽のポインタを構築します。次に、この構造体のポインタをたどって任意の書き込みを取得できます。
libcアドレスが漏洩するのは、ヒープがmmapを使用して拡張されると、mmapによって割り当てられたメモリがlibcから固定オフセットを持つためです。
最後に、任意の書き込みが悪用され、__free\_hook
のアドレスにone gadgetが書き込まれます。
ユーザー入力行を読み取るgetline
関数にNULLオフバイワンの脆弱性があります。この関数は、コンテンツの「キー」を読み取るために使用され、コンテンツ自体ではありません。
書き込みでは、最初に5つのチャンクが作成されます:
chunk1 (0x200)
chunk2 (0x50)
chunk5 (0x68)
chunk3 (0x1f8)
chunk4 (0xf0)
トップチャンクとの統合を避けるためのチャンク防御 (0x400)
次に、チャンク1、5、3が解放されます:
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]