web-dev-qa-db-ja.com

Heartbleed:なぜクライアントがメッセージの長さを提供するのですか?

「このバグの修正は簡単です。メッセージの長さが実際に着信要求の長さと一致することを確認してください。」

なぜクライアントに長さを報告させるのですか?

着信リクエストの長さがわかっている場合、そこからメッセージの長さを推測することはできませんか?

(これはプログラミングとプロトコル設計の質問です。)

67
Elliot

ライブネス(キープアライブ)チェックを目的としたTLSの場合、次の理由はありません。

  1. ハートビートリクエスト/レスポンスヘッダーのペイロードサイズフィールドをエンコードします(ペイロードの長さは、OpenSSLコードのレコードレイヤーrrec.lengthから取得されます。これから固定HBヘッダーサイズを差し引くだけです)。
  2. HBを可変サイズにする-小さなHBサイズ(約4〜32バイトの範囲)は完全に機能します-シーケンス番号としては十分ですが、
  3. ペイロードにパディングを追加する、または
  4. PMTU検出を実行します(以下で定義)

そのため、通常のTLSに関して設計に欠陥があり、複雑すぎます。注TLSは、すべてのHTTPSトラフィックを暗号化する、私たちが本当に関心を持っている広く使用されているプロトコルです。

vulnerable OpenSSL commit で生成されたすべてのハートビート要求には小さな固定ペイロード(18バイト)があり、受信したHB応答を処理するとき、OpenSSLはその最初の2バイトのみをチェックしますHBシーケンス番号が含まれています。ソース: t1_lib.c (すべてのTLS HBコードを含む)HBを生成するとき( tls1_heartbeat /でのみ説明) )、ペイロードサイズを18に固定します。 tls1_process_heartbeat でのHB応答の処理も、ペイロードが正確に18の場合にのみ意味のある処理を行います。 TLSのリクエストは、HTTPSを損なう脆弱な部分 です。

背景

主張された正当化に到達する前に、3つの概念を紹介する必要があります。DTLS、PMTU、およびPMTU検出はすべて、活性チェックとは関係ありませんが、Heartbeat拡張のその他の提案された使用法を扱います。慣れている場合は、提案された正当化に進んでください。

TLS(TCPでの暗号化)およびDTLS(UDPでの暗号化)

通常のTLSは、TCPに加えて暗号化を追加します。 TCPは、信頼性の高いトランスポートストリームを提供するトランスポート層プロトコルです。つまり、アプリケーションが再構築されたデータストリームを受信します。 TCPは輻輳制御も提供します(輻輳が原因でパケットがドロップされている場合、TCPはパケットのレートを調整しますすべてのHTTP、HTTPS、SFTPトラフィックはTCP経由で送信されます。

データグラムTLS(DTLS)は、UDP(およびアプリケーションがパケットの送信方法を完全に制御できるDCCPなどの同様のデータグラムプロトコル)に暗号化を追加する新しいプロトコルです。これらは、信頼性の高いストリームを提供しないトランスポート層プロトコルですが、アプリケーションによって制御されるクライアント/サーバーアプリケーション間で直接パケットを送信します。 TCPを使用すると、パケットが失われた場合、パケットが自動的に再送信され、失われたパケットが通過するまで、次のパケットの送信が遅延します。UDPは、アプリケーションにパケットレベルの制御を提供します。これは、リアルタイム通信によく使用されます双方向のビデオチャットのようです。パケットA、B、C、Dが送信されたがパケットCが失われた場合、パケットDをユーザーに表示する前にCが再送信されるのを待つのは意味がありません。一時停止。

[〜#〜] pmtu [〜#〜]

DTLSの場合、 パス最大伝送ユニット を知っていることが望ましい。ルーター間の単一リンクのMTUは、送信できる最大パケットサイズです。ルーターやリンクの種類が異なると、多くの場合、異なるMTUがサポートされます。パスMTU(パケットがネットワークを通過するパスの最小MTU)は、ネットワークを通過するパスのプロパティであるため、通常は事前にはわかりません。 PMTUよりも大きいデータグラムを送信する場合、最小のMTUポイントでフラグメント化する必要がありますが、これはいくつかの理由で望ましくありません(非効率なフラグメント化されたパケットは、ファイアウォール/ NAT、アプリケーションレイヤーへの混乱、およびIPv6によって混乱する可能性があります。設計はパケットを断片化しません)。したがって、DTLSのコンテキストでは、RFCはレコードレイヤーからのデータを強制的に単一のDTLSパケット(PMTUよりも小さい)に収めます。 (TLSを使用すると、これらのPMTUの問題はTCP=レベルで処理されます。TLSはPMTUに依存しないため、アプリケーション層では処理されません)。

PMTU検出

PMTUを検出するプロトコルがあります。具体的には packetization layerパスMTU検出(RFC 4821) です。このコンテキストでは、さまざまなサイズのパケット(フラグメント化しないように構成)を送信してネットワークを調査し、パケットがネットワークを通過したかどうかに応じて、PMTUの上限と下限を追跡します。これはRFC4821で説明されています。プローブパケットが通過した場合は、下限を上げ、それが失われた場合は、上限/下限が近くなるまで上限を下げ、DTLSパケットの上限サイズを設定するために使用される推定PMTUを取得します。


ペイロードヘッダー、パディング、最大2バイトのサイズフィールドを持つHBの正当化された正当化

ハートビートRFC RFC6520 は、DTLSのパスMTU検出にハートビートを使用できると述べています。

5.1。パスMTUディスカバリー

[RFC6347]のセクション4.1.1.1で説明されているように、DTLSはパスMTUディスカバリを実行します。パスMTUディスカバリを実行する方法の詳細な説明は、[RFC4821]で提供されています。必要なプローブパケットは、HeartbeatRequestメッセージです。

DTLSアプリケーションはPMTUを推定する必要があります。ただし、これはDTLSでは行われず、DTLSを使用するアプリケーションで行われます。 DTLS RFCの引用部分 RFC6347 のセクション4.1.1.1を見ると、「一般的に、DTLSの哲学はPMTUの発見をアプリケーションに任せることです」と述べています。 DTLSがPMTUを心配する必要がある理由について、3つの警告が続きます(DTLSアプリケーションは、データの有効なPMTUサイズを取得するためにDTLSヘッダーを差し引く必要があります。DTLSは、ICMP "データグラムが大きすぎます"をアプリケーションレイヤーに戻す必要があり、DTLSハンドシェイクはPMTUよりも小さくする必要があります。DTLSRFCの前半では、DTLSレコードはPMTUよりも小さい単一のデータグラムに収まる必要があることを宣言しているため、DTUを使用するアプリケーションでPMTU検出/推定を行う必要があります。

PMTUディスカバリーでは、ペイロードの長さを説明する小さなフィールド、大量の任意のパディング、そしてエコーバックするものがあることは理にかなっています、私はあなたに送り返すだけですが、このサイズのMTUでリクエストを受け取りましたシーケンス番号(効率のために、応答のパディングを削除することができます)。 payload のサイズを記述してペイロードを約4〜32バイトより大きくできるようにしても意味がないので、ペイロードサイズは次のように修正または記述できます。任意の長いパディングを連結できる場合でも、1バイトのフィールド。

クレームの分析

OpenSSL HBの実装とHB RFCの説明では、このPMTU検出プロトコルについて説明または実行していません。 MTUがコードに含まれていません。 OpenSSLは、TLSおよびDTLSでHB要求を生成するメカニズムを1つだけ提供しますが、固定サイズ(18バイトのペイロード、構成不可)です。

  1. OpenSSLコードでPMTUディスカバリをプローブするために一連のHBを送信する機能、またはプローブプロセスでのHBの使用方法の詳細な説明はありません。
  2. HBがフラグメント化しないように構成されていることを示すものはありません(したがって、このプローブ方法で使用することもできます)。
  3. HBを使用してPMTUディスカバリーを行う場合、アプリケーション作成者は、クライアントとサーバーのすべてのコードを自分で作成する必要があります。
  4. ペイロードフィールドは、PMTUを見つけるという状況でも、1バイトである必要があります(固定されていなくても)
  5. クライアント/サーバーアプリケーションで任意のタイプのパケットではなく、HBパケットを使用するためにプロービングプロセス全体を実行しない理由はありません。たとえば、通常のUDPパケットを使用します。
  6. PMTU検出はDTLSのコンテキストでのみ意味をなすので、これらの完全に不要な機能がTLSハートビートに存在するのはなぜですか-PMTUを認識する必要のないアプリケーションですか?

せいぜいこれは、YAGNI機能を組み込んだ(TLSの)深刻な欠陥のある設計であり、健全性テストなしでユーザー提供のヘッダーフィールドを完全に信頼するように不正にコード化されていました。最悪の場合、PMTUセクションは、正当化のいくつかの類似性を提供する脆弱なコードの挿入を可能にする複雑なカバーストーリーでした。


IETF TLSメーリングリストを検索する

IETF TLSメーリングリスト を検索すると、興味深いナゲットを見つけることができます。ペイロード/パディングの長さがuint16であり、破棄する場合にパディングがあるのはなぜですか? PMTU検出 。同じ質問者(JuhoVähä-Herttua)は パケットの検証を強く好むと述べています。ペイロードの長さ、パディングの長さを読み取り、レコード長(マイナスヘッダー) と一致することを確認します。また、 Simon Josefsson

私は、任意のペイロードを許可することに関して、穏やかな懸念を1つ持っています。これの理由は何ですか? TLSのサイドチャネル用に開きます。また、標準化されていないデータを送信するために悪用される可能性もあります。さらに、任意のサイズのペイロードを許可する理由はありますか?私の考えでは、payload_length、payload、paddingフィールドは私には不要のようです。

MichaelTüxenの応答 はほとんど不十分で(おそらく、RTTを計算するためにいくつかの機能を追加する必要があるかもしれません)、「ここでのポイントは相互運用性のために、ペイロードが何であれ、それが反映されることだけが重要です。」

また、 ランダムなパディングの理由 "[we] randomize ...ハートビートメッセージのデータをランダム化して、弱いまたは欠陥のある暗号から発生する問題の先頭を試みます。" 続いて、「パケット内でランダム化されたデータを使用することで、将来起こりうる暗号の欠陥をどのように解決できるかを論じている文書や暗号のドキュメントはありますか?」、続いて、確定的な認証済み暗号化に関する文書が続きます。 responseはすばらしい

確かに、これはCBCやCTRのような一般的な暗号化モードではありません。ランダムキーを暗号化するように特別に設計されているため、そのランダム性に依存します。典型的な暗号化モードは、特定のプレーンテキスト暗号化をランダムな暗号化から誰かが区別することを防ぐように特別に設計されています。

現在、TLSでサブリミナルチャネルを使用する場合、ハートビート拡張が無制限のチャネルを提供します。

そのコメントが扱われなかったことは興味深いです。 (「まあ、それはまったく別の問題です...」とコメントする他の誰かを除いて)。

32
dr jimbob

私はこの問題についての決定的な「公式の」答えを知りませんが、これは一般性と一貫性の試みの一部のようです。 SSL/TLS 標準では、すべてのメッセージは特定の プレゼンテーション言語 を使用して、通常のエンコーディングルールに従います。プロトコルのどの部分も、レコード長から「長さ」が異なります。

啓発の詳細の1つはClientKeyExchangeメッセージです。RSAキー交換を使用した SSL 3. では、そのハンドシェイクメッセージの内容は「生の」暗号化結果です(つまり、サーバーの場合は256バイト)。 2048ビットのRSAキーと4バイトのハンドシェイクメッセージヘッダーを使用します); TLS 1. 以降のバージョンでは、暗号化の結果は、長さを含む2バイトのヘッダーが追加された「不透明なベクトル」になるため、256ではなく258バイトであり、さらに4バイトが追加されます。ハンドシェイクメッセージヘッダー。この変更は、パケット長からの推論をできるだけ少なくして、厳密な規則性を達成するという標準設計者の意志を示しています。

外部構造から長さを推測しないことの1つの利点は、後でオプションの拡張を含めることがはるかに容易になることです。これは、たとえばClientHelloメッセージで行われました。


より高い視点から見た場合、TLSは半分しか完成していません。プロトコルとしてのTLSは、構造化データを交換する必要があります。送信側と受信側は、あいまいさ、およびできればバッファオーバーフローもない状態で、このようなデータをエンコードおよびデコードできる必要があります。そのための1つの戦略は、次のことです。

  • 構造化要素の厳密な規則的なエンコードルールを定義します。たとえば、すべての要素の前に、要素の長さを含むヘッダーを置くように定義します。
  • プロトコル標準の一部としてすべてのメッセージの構造とタイプを表現する明確な言語を定義します。それがRFCの「プレゼンテーション言語」です。
  • RFCからプレゼンテーション言語を貼り付け、すべての長さや値の範囲などを体系的にチェックして、すべてのメッセージのエンコードとデコードを処理するエンコーダー/デコーダーの実装を生成する汎用コンパイラソフトウェアを記述します。

この戦略の実施形態は ASN.1 です。 ASN.1は、たとえばX.509証明書で使用されます。 ASN.1コンパイラを使用すると、(理論的には) X.509標準 からASN.1構文を貼り付け、X.509証明書用の完全なエンコーダ/デコーダエンジンを取得できます(私はそれを行いましたが、私自身のASN.1コンパイラを書くことを含み、文字列と日付のASN.1型がLSDのヒヒによって発明されたように見えますが、全体的なスキームはまだ機能しているという事実を含むいくつかの「癖」があります。

別の実施形態は [〜#〜] xml [〜#〜] で、 XMLスキーマ を「プレゼンテーション言語」として:スキーマと入力データをXMLパーサーにプッシュします。 、およびエラーコード以外のものが生成された場合、すべてのデータがスキーマに準拠していることを知っているので、デコードされた構造化ツリー内を歩くことができます。繰り返しになりますが、これは理論であり、理論的にはニースです。

TLSの「プレゼンテーション言語」は、ここでは少し不足しています。コンパイラはありません。その言語は「コンピューター言語」のように見えますが、人間が読むためのものでした。そのため、うまく機能します。ただし、これはdeveloperがその言語をエンコーダー/デコーダーに転記する必要があることを意味します。開発者は、ステップを忘れないように注意する必要があります。そして、まさにそれが「ハートブリード」バグで発生したものです。悲惨な結果をもたらす可能性のあるステップが忘れられました。

37
Thomas Pornin

RFC6520(ハートビート拡張) を調べると、ペイロードの後に​​パディングがあります。したがって、ペイロードがどこで終わり、パディングが始まるかを知るためには、長さが必要です。それとは別に、設計が過剰に設計されていることがわかります。この拡張の両方の理由は、(異なるサイズのメッセージを使用することによって)PMTUを可能にすることと、ハートビートにもう一方の端がまだ生きているかどうかを確認すること、またはいくつかのタイムアウトカウンターをリセットすることですミドルボックスの状態。これらのシナリオでは、ユーザー指定のペイロードを反映させる必要はありませんでした。

また、セキュリティの観点からは、このように高度に設計されたプロトコルでは、本当に必要なものだけをテストし、将来のトラブルに備えて頼みます。

14
Steffen Ullrich