Heap Overflow
Last updated
Last updated
AWSハッキングの学習と練習:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングの学習と練習:HackTricks Training GCP Red Team Expert (GRTE)
ヒープオーバーフローは、ヒープ内でのスタックオーバーフローのようなものです。基本的に、ヒープにデータを格納するためのスペースが予約され、格納されたデータが予約されたスペースよりも大きかったことを意味します。
スタックオーバーフローでは、スタックからレジスタ(命令ポインタやスタックフレームなど)が復元されることがわかっており、これを悪用する可能性があります。ヒープオーバーフローの場合、ヒープチャンクにはデフォルトで機密情報は格納されていないことがあります。ただし、機密情報やポインタが含まれる可能性があるため、この脆弱性の重大性は、どのデータが上書きされるかと攻撃者がこれをどのように悪用できるかに依存します。
オーバーフローオフセットを見つけるためには、スタックオーバーフローと同じパターンを使用できます。
スタックオーバーフローでは、脆弱性がトリガーされる時点でスタックに存在するデータと配置がかなり信頼できます。これは、スタックがリニアであり、常に増加しているため、プログラムの実行中の特定の場所では、スタックメモリが通常同様の種類のデータを格納し、各関数によって使用されるスタック部分の末尾にいくつかのポインタがある特定の構造を持っているためです。
しかし、ヒープオーバーフローの場合、使用されるメモリはリニアではなく、割り当てられたチャンクは通常メモリの別々の位置に配置されています(隣接しているわけではありません)。これは、サイズによって割り当てを分離するビンやゾーンと、新しいチャンクを割り当てる前に以前に解放されたメモリが使用されるためです。ヒープオーバーフローに対して脆弱性が見つかった場合、望ましいオブジェクトをオーバーフローの対象となるオブジェクトの隣に配置する信頼性の高い方法を見つける必要があります。
そのために使用されるテクニックの1つがHeap Groomingです。たとえば、この投稿で使用されています。この投稿では、iOSカーネルで、ゾーンがメモリを格納するのに十分なメモリがなくなると、カーネルページが拡張され、このページが期待されるサイズのチャンクに分割され、順番に使用されます(iOSバージョン9.2までは、これらのチャンクはこれらの攻撃の複雑さを増すためにランダムな方法で使用されます)。
したがって、ヒープオーバーフローが発生する前述の投稿では、オーバーフローしたオブジェクトを被害者の順序と衝突させるために、複数のスレッドによって複数の**kallocs
が強制され、すべての空きチャンクが埋められ、新しいページが作成されるようにする**必要があります。
特定のサイズのオブジェクトでこの埋め込みを強制するために、iOS mach portに関連付けられたアウトオブラインの割り当てが理想的な候補です。メッセージのサイズを作成することで、kalloc
の割り当てのサイズを正確に指定し、対応するmach portが破棄されると、対応する割り当てがすぐにkfree
に戻されます。
その後、これらのプレースホルダーのいくつかを解放できます。kalloc.4096
フリーリストは、後入れ先出しの順序で要素を解放するため、いくつかのプレースホルダーが解放され、エクスプロイトがオーバーフローの対象となるオブジェクトを割り当てようとする間に複数の被害者オブジェクトを割り当てようとする場合、このオブジェクトが被害者オブジェクトに続く可能性が高いです。
このページでは、次のチャンクのprev in useビットとprevサイズの位置を上書きすることで、使用中のチャンクを統合(未使用と見なすことで)し、それを再度割り当てして、異なるポインタで使用されているデータを上書きできることを示す基本的なヒープオーバーフローエミュレーションが示されています。
protostar heap 0からの別の例では、ヒープオーバーフローを悪用して、winner関数を呼び出してフラグを取得するCTFの非常に基本的な例が示されています。
protostar heap 1の例では、バッファオーバーフローを悪用することで、ユーザーからの任意のデータが書き込まれるアドレスを近くのチャンクに上書きすることが可能であることが示されています。
https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/のページには、実行されるコマンドがオーバーフローしたチャンクから次のチャンクに格納されるヒープオーバーフローの例があります。そのため、簡単なエクスプロイトでそれを上書きして実行されるコマンドを変更することが可能です。
ヒープオーバーフローを取得するために整数オーバーフロー脆弱性を使用します。
オーバーフローしたチャンクのstruct
内の関数へのポインタを破壊して、system
などの関数を設定してコード実行を取得します。