web-dev-qa-db-ja.com

Heartbleedエクスプロイトはどのようにしてさらに可能ですか?

Heartbleed OpenSSLの脆弱性について読み、その概念を理解しました。しかし、私が理解していないのは、長さとして64kを渡し、サーバーが64kbのランダムデータを返す部分です。これは、実際に64kbのエコーメッセージまたは1バイトを渡したかどうかをチェックしないためです。

しかし、サーバー上のプロセスが64 KBのランダムデータをRAMから返すことはどうして可能でしょうか。

オペレーティングシステムは実際のRAM=へのアクセスを禁止し、1つのプロセスが他のプロセスのメモリコンテンツにアクセスできない仮想メモリへのアクセスのみを許可することになっているのではないですか?

OpenSSLはカーネルモードで実行され、すべてのRAMにアクセスできますか?

プロセスが明示的に割り当てていないメモリにアクセスしようとした場合、セグメンテーション違反が発生すると予想します。 OpenSSLプログラム自体を実行しているプロセスから64 kbのランダムデータを取得することは理解できますが、送信できるサーバーの完全なRAM)を確認する方法さえわかりませんクライアントに戻る。

PDATE: @ paj28のコメント、そうです、私がこれについて不思議に思ったのは、まさに誤った情報でした。あなたが言ったように、公式のheartbleed.comアドバイザリでさえも誤解を招くように表現しています(ただし、私たちの技術者よりもはるかに幅広いユーザーを対象としており、シンプルにしたいと考えていたためです)

参考までに、heartbleed.comがそれをどのように述べているかを示します(私を強調):

Heartbleedバグにより、インターネット上の誰でもシステムのメモリを読み取る OpenSSLソフトウェアの脆弱なバージョンによって保護されます。

仮想/物理マシンの完全なRAM=を暗示する技術者向け。

126
Talha Sayed

@ paj28のコメントは要点をカバーしています。 OpenSSLは共有ライブラリであるため、それを使用するプロセスと同じユーザーモードアドレス空間で実行されます。他のプロセスのメモリはまったく見えません。そうでなければ示唆されたものはすべて間違っていました。

ただし、OpenSSLによって使用されているメモリ(おそらく、Heartbleedがオーバーリードするバッファーの近くのもの)は、機密データでいっぱいです。具体的には、最近または今後の送信の暗号文と平文の両方が含まれている可能性があります。サーバーを攻撃すると、これは、他のユーザーがサーバーに送信したメッセージと、それらのメッセージに対するサーバーの応答が表示されることを意味します。これは、セッショントークンと個人情報を盗むための良い方法であり、おそらく誰かのログイン資格情報も盗むでしょう。 OpenSSLによって保存されるその他のデータには、対称暗号化キー(バルクデータの暗号化とTLSによる整合性に使用)と秘密キー(サーバーのIDを証明するために使用)が含まれます。これらを盗む攻撃者は、侵害されたTLS通信をリアルタイムで盗聴(または変更)するか、サーバーを偽装することができます(ネットワークの中間者の位置を想定しています)。

さて、Heartbleedには奇妙なことが1つあります。通常、プロセス内の任意のヒープアドレスから64kのデータを読み取ろうとすると、未割り当てのメモリアドレス(仮想メモリが何もバックアップされていないため使用できない)に遭遇する可能性がかなりあります。早く。プロセスのアドレス空間におけるこれらの穴はかなり一般的です。プロセスが不要になったメモリを解放すると、OSがそのメモリを解放して他のプロセスが使用できるようになるためです。プログラムがふるいのようにメモリをリークしていない限り、通常、現在使用されているデータ以外のデータはメモリにあまりありません。割り当てられていないメモリを読み取ろうとすると(たとえば、解放されたメモリにアクセスしようとすると)、読み取りアクセス違反(Windowsの場合)/セグメンテーション違反(* nixの場合)が発生し、プログラムがクラッシュします(実行する前にクラッシュします)。データの返信など)。これはまだ(サービス拒否攻撃として)悪用可能ですが、攻撃者にそのすべてのデータを取得させることほど悪くはありません。

Heartbleedでは、プロセスがクラッシュすることはほとんどありませんでした。 OpenSSLは、明らかにプラットフォームのメモリ管理ライブラリが遅すぎる(または何か、私はこの決定を正当化しようとはしません)と判断し、大量のメモリを事前に割り当て、独自のメモリ管理関数を使用していることがわかりましたその中で。これはいくつかのことを意味します:

  • OpenSSLがメモリを「解放」しても、OSに関する限り、実際には解放されないため、プロセスはメモリを引き続き使用できます。 OpenSSLの内部メモリマネージャーはメモリが割り当てられていないと考えている可能性がありますが、OSに関する限り、OpenSSLを使用するプロセスはまだそのメモリを所有しています。
  • OpenSSLがメモリを「解放」すると、free関数を呼び出す前に明示的にデータを消去しない限り、そのメモリは「解放」される前の値をすべて保持します。つまり、実際にはまだ使用されていない多くのデータを読み取ることができます。
  • OpenSSLが使用するメモリヒープは連続しています。 OSに関する限り、ギャップはありません。したがって、バッファのオーバーリードが割り当てられていないページに実行される可能性は非常に低いため、クラッシュする可能性はほとんどありません。
  • OpenSSLのメモリ使用は局所性が非常に高く、つまり、OSメモリアロケータの気まぐれでアドレス空間全体に分散するのではなく、比較的狭い範囲のアドレス(事前に割り当てられたブロック)に集中します。そのため、64KBのメモリ(32ビットプロセスの典型的な2GBの範囲の隣でさえ、64ビットプロセスの巨大な範囲よりはるかに少ない)を読み取ると、次のような大量のデータを取得する可能性があります。現在(または最近)使用されていますが、そのデータは、おそらく別々の割り当ての束の結果として存在しています。
209
CBHacking

プロセスが明示的に割り当てていないメモリにアクセスしようとした場合、セグメンテーション違反が発生すると予想します

ここが誤解です。

破損したメモリアクセスcouldはセグメンテーション違反を引き起こしますが、実際には、要求されたメモリアドレスが現在のプロセスのアドレス空間(たとえば、解放したばかりの変数)内にある場合、これはほとんど発生しません。

そのため、メモリアクセスのバグを見つけるためにセグメンテーションエラーに頼るべきではありません。