web-dev-qa-db-ja.com

ヒープオーバーフローを使用した情報開示攻撃

ASLRを無効にするための一般的な戦略は、バッファオーバーフローバグと情報開示バグの両方を見つけることです。しかし、クラッシュ/死ぬたびに自動的に再起動するサーバーを攻撃する場合、バッファオーバーフローのバグで十分でしょうか?そのバッファオーバーフローバグを使用して、情報開示機能を提供することはできますか?

シナリオを具体化させてください。ネットワークからのリクエストを処理し、クラッシュ時に自動的に再起動するサーバープログラムがあるとします。また、サーバーに(ヒープに割り当てられたバッファーBの)バッファーオーバーランの脆弱性があり、送信することで確実に悪用できるとします。サーバーへの適切に作成されたリクエスト。また、サーバーがクラッシュしたときに検出できると仮定します(たとえば、メモリを破壊してsegfaultを引き起こしたリクエストを送信したためにクラッシュした可能性があります。いずれにしても、選択したリクエストを送信して、それがそのリクエストを処理しようとしたときにクラッシュしたかどうか)。サーバーはASLRを使用しており、コードインジェクション攻撃をマウントできるようにASLRをランダム化解除したいのですが、個別の情報開示のバグは知りません-バッファオーバーランの脆弱性は、私が対処しなければならないすべてです。

このバッファオーバーランの脆弱性を情報開示に使用して、Bの後のメモリの内容を知ることはできますか?

これは私が想像している種類の攻撃の例です:

オーバーフロー可能なバッファーBが512バイト長であり、Pの直後に8バイトの秘密のポインターBが格納されているとします。リクエストのフィールドFが長さチェックなしでBにバイト単位でコピーされるとします。

Fに513バイトの値を含むリクエストを送信すると、Bにコピーされます。私の値の513番目のバイトがPの最初のバイトと異なる場合、Pの値は破損し、プログラムが後でPを逆参照すると想定すると、プログラムはおそらくこの要求の処理中にクラッシュします。一方、値の513バイトがPの最初のバイトと一致する場合、Pは変更されず、プログラムはおそらくクラッシュしません。

したがって、フィールドFの513番目のバイトの値がそれぞれ異なる256のリクエストを送信することを想像できます。それらのうちの255がサーバーをクラッシュさせ、1つはクラッシュさせない場合、Pの最初のバイトの値がすぐにわかります。これで、Pの各バイトを学習するまで続けることができます。これは、プログラムがASLRを使用している場合に役立ちます。ポインタPの値を学習することで、メモリの一部をランダム化できます。

これは単なる例です。実際には、Bの終わりの後、ヒープに格納されている次のオブジェクトの前に未使用のスペースがあると想像しますが、これらの手法を適用してその状況にも対処する方法を想像できます(たとえば、Bの後のバイトがが使用されていない場合は、何でも上書きでき、サーバーはクラッシュしません。そのため、使用されていない場所を簡単に検出し、Bの後に次のオブジェクトが見つかるまで攻撃を続けることができます。

この攻撃は実際に機能しますか?自動的に再起動されるサーバーでヒープオーバーフローが発生し、クラッシュを検出する方法がある場合、ASLRを無効にする効果的な方法を提供しますか?

私が見落とした、これが機能しなくなるハードルはありますか?たとえば、ヒープ内のオブジェクトへのメモリ割り当てが非決定的でランダムである場合、攻撃は失敗すると想像できます。しかし、プラットフォームはそれをしますか?同じ入力で同じプログラムを2回実行した場合、ヒープ内のオブジェクト間の相対オフセットは実際には確定的ですか?


バッファオーバーフローにより、Bを完全に攻撃者の制御下にある任意のバイナリデータで上書きできると想定しています。 (この場合、データは強制的にNULで終了するため、strcpy()または文字列関連のオーバーフローでは攻撃は機能しません。)また、fork( )、またはその他の理由により、サーバーが再起動されるたびにメモリレイアウトの一部が同じになります。 (たとえば、ライブラリはサーバーを再起動するたびに同じベースアドレスにあるため、これはWindowsとMacで自動的に保持され、Linuxの非PIEプロセスでも保持されます。)

クレジット:私は、情報開示の目的でスタック割り当てバッファのバッファオーバーフローバグを悪用するために最近読んだ方法に触発されました。これについては、IEEE Security&Privacy 2014で最近公開された Blind ROPペーパー で説明されています。バッファBがスタックに割り当てられている場合の方法を示しています。この質問では、バッファBがヒープ上にある場合にそれらの手法を一般化できるかどうかを尋ねています。

8
D.W.

お気づきのように、失敗するたびにプログラムはクラッシュします。 ASLR実装のオペレーティングシステム/堅牢性、およびプログラムの再起動方法によっては、次のような結果になる場合があります。

  1. 同じレイアウト(たとえば、execなしのforkを使用してプログラムを再起動する場合);
  2. 部分的に異なるレイアウト(例:Linuxの非PIE実行可能ファイルの非ライブラリコードアドレス、またはWindowsおよびMac OS Xの一部のバージョン(おそらくすべて?)のライブラリコードアドレス)
  3. 完全にランダムなレイアウト(PIE Linux実行可能ファイルなど)。

したがって、推測しようとしている値がプログラムの再起動間で静的でない場合は、正しく推測したかどうかを判断できますが、誤って推測するとすぐにプログラムが再起動し、情報がなくなります。したがって、段階的に推測しても何も得られません。

明らかにASLRは絶対的な保護を提供せず、その効果は一部の領域のみがランダム化されている場合、または同じレイアウトが複数のプログラムの実行で使用されている場合に特に制限されますが、依存しないヒープオーバーフローで一般的な攻撃を行うようです問題のプログラムの非常に具体的な詳細は、ブラインドROPペーパーのスタックオーバーフローで行われるように、かなり難しいでしょう。

5
jbms