このコンテンツは自動機械翻訳サービスによる翻訳版であり、皆さまの便宜のために提供しています。原本の英語版と異なる誤り、省略、解釈の微妙な違いが含まれる場合があります。ご不明な点がある場合は、英語版原本をご確認ください。
2025年12月、CloudflareはHTTP/1.xの報告を受けました。Pingoraをイングレスプロキシの構築に使用する際の、Pingoraオープンソースフレームワークにおけるリクエストスマグリングの脆弱性。本日は、これらの脆弱性の仕組みと、Pingora 0.8.0でどのようにパッチを適用したかについてお話しします。
脆弱性はCVE-2026-2833、CVE-2026-2835、およびCVE-2026-2836です。これらの問題は、当社のバグバウンティプログラムを通じてRajat Raghav氏(xclow3n)から責任を持って報告されました。
CloudflareのCDNと顧客トラフィックに影響はなかったことが、当社の調査でわかりました。Cloudflareのお客様は、何もする必要がなく、影響も検出されませんでした。
Cloudflareのネットワークのアーキテクチャにより、これらの脆弱性は悪用されませんでした。Pingoraは、CloudflareのCDNのイングレスプロキシとして使用されていません。
しかし、これらの問題は、インターネットに公開されるスタンドアロンのPingoraデプロイメントに影響を与え、攻撃者に以下を可能にする可能性があります。
Pingoraプロキシ層セキュリティ制御をバイパス
クロスユーザーハイジャック攻撃(セッションまたは資格情報の盗難)のために、HTTPリクエスト/レスポンスをバックエンドと非同期化する
Pingoraプロキシ層キャッシュで共有バックエンドからコンテンツを取得
修正とハードニングを加えたPingora 0.8.0をリリースしました。Cloudflareのお客様は影響を受けませんでしたが、Pingoraフレームワークのユーザーはできるだけ早くアップグレードすることを強くお勧めします。
レポートには、非同期攻撃を引き起こす可能性のあるいくつかの異なるHTTP/1攻撃悪意のあるペイロードについて説明されています。このようなリクエストは、リクエスト本文がどこで終わるかについて、プロキシとバックエンドとの不一致を引き起こす可能性があり、2番目のリクエストがプロキシ層のチェックを通過して「スニッフィング」される可能性があります。研究者は、基本的なPingoraリバースプロキシがリクエスト本文長をどのように誤って解釈し、それらのリクエストをNode/Expressやuvicornなどのサーバーバックエンドに転送するかを検証するための概念実証を提供しました。
報告を受けた当社のエンジニアリングチームは、直ちに調査を行い、報告者自身も確認したように、Cloudflare CDN自体に脆弱性がないことを確認しました。しかし、チームは、Pingoraが共有バックエンドのイングレスプロキシとして機能するときに脆弱性が存在することも検証しました。
設計上、Pingoraフレームワークは、RFCに厳密に準拠していないエッジケースのHTTPリクエストまたはレスポンスを許可しています。これは、レガシーHTTPスタックを持つお客様のために、この種のトラフィックを受け入れなければならないためです。しかし、可能性にも制限を受けますが、Cloudflare自体が脆弱性にさらされることを避けるためには限界があります。
この場合、Pingoraは、HTTP/1スタック内でリクエストボディがRFC非準拠の解釈をするため、こうした非同期攻撃が可能でした。Cloudflare内のPingoraデプロイメントは、イングレストラフィックの影響に直接さらされず、Pingoraサービスに到着した本番用トラフィックは、こうした誤解の影響を受けないことが確認されました。したがって、2025年5月に公開された以前のPingora密輸の脆弱性とは異なり、Cloudflareのトラフィック自体を悪用することはできませんでした。
これらの攻撃悪意のあるペイロードがどのように機能したかを、ケースバイケースで説明します。
1. 101ハンドシェイクなしの早期アップグレード
最初のレポートでは、Upgrade ヘッダー値を持つリクエストが、バックエンドがアップグレードを受け入れる前に(101 Switching Protocols を返すことで)、PingoraがHTTP接続上の後続のバイトを即座に通過させることが示されました。このように、攻撃者は同じ接続上で、アップグレードリクエストの後に、2つ目のHTTPリクエストをパイプライン化することができます。
GET / HTTP/1.1
Host: example.com
Upgrade: foo
GET /admin HTTP/1.1
Host: example.com
Pingoraは、最初のリクエストだけを解析し、残りのバッファリングされたバイトを「アップグレードされた」ストリームとして扱い、Upgradeヘッダーにより「パススルー」モードでバックエンドに直接転送します(レスポンスが受信されるまで)。
これは、RFC 9110に準拠したHTTP/1.1アップグレードプロセスの意図された動作とは全く異なります。後続のバイトは、101 Switching Protocolsヘッダーが受信された場合、アップグレードされたストリームの一部としてのみ解釈されます。代わりに、200 OKレスポンスが受信された場合、後続のバイトはHTTPとして引き続き解釈されます。
アップグレードリクエストを送信し、部分的なHTTPリクエストをパイプラインで行う攻撃者は、非同期攻撃を引き起こす可能性があります。Pingoraは、バックエンドサーバーが200でアップグレードを拒否した場合でも、両方を同じアップグレードされたリクエストとして誤って解釈します。
不適切なパススルーを介して、101以外のレスポンスを受信したPingoraデプロイは、2番目の部分的なHTTPリクエストをそのまま上流に転送し、Pingoraユーザー定義のACL処理またはWAFロジックをバイパスして、上流への接続をポイズニングする可能性があります。これにより、別のユーザーからの後続のリクエストが/adminレスポンスを不適切に受け取る可能性があります。
攻撃悪意のあるペイロードの後、Pingoraとバックエンドサーバーは「非同期」状態になっています。バックエンドサーバーは、Pingoraが転送した部分的な/attackリクエストヘッダーの残りが完了したと考えるまで待ちます。Pingoraが別のユーザーのリクエストを転送すると、バックエンドサーバーから見ると2つのヘッダーが組み合わされ、攻撃者はそのユーザーの応答をポイズニングしています。
それ以来、Pingoraにパッチを適用して、アップストリームが101 Switching Protocolsで応答すると、後続のバイトの解釈を切り替えるようにしました。
Cloudflareが影響を受けなかったことを2つの理由で確認しました。
イングレスのCDNプロキシは、このような不適切な動作をしません。
内部Pingoraサービスへのクライアントは、HTTP/1リクエストをパイプライン化しようとしません。さらに、これらのクライアントが直接通信するPingoraサービスは、Connection: closeヘッダーを挿入することで、これらのアップグレードリクエストでキープアライブを無効化します。これにより、同じ接続を介して送信される追加のリクエストが送信され、その後、維持されることを防ぎます。
2. HTTP/1.0、クローズドリミット、転送エンコーディング
レポーターは、思われるより典型的な「CL.TE」デシンク型攻撃も実証しました。この攻撃では、PingoraプロキシがContent-Lengthをフレーミングとして使用し、バックエンドがTransfer-Encodingをフレーミングとして使用します。
GET / HTTP/1.0
Host: example.com
Connection: keep-alive
Transfer-Encoding: identity, chunked
Content-Length: 29
0
GET /admin HTTP/1.1
X:
レポーティングの例では、Pingoraは最初のGET /リクエストヘッダーの後に後続のバイトをすべてそのリクエスト本文の一部として扱いますが、node.jsバックエンドサーバーは本文がチャンク化された、長さゼロのチャンクで終わると解釈します。実際には、いくつかの事が起こっています。
Pingoraのチャンク化されたエンコーディングの認識は非常に最低限であり(Transfer-Encodingが「chunked」であるかどうかの確認のみ)、エンコーディングまたはTransfer-Encodingヘッダーは1つしか存在しないと仮定しました。しかし、RFCは、チャンク化されたフレーミングを適用するために、最終エンコーディングがチャンク化されることを義務付けているにすぎません。そのため、RFCによると、このリクエストにはメッセージ本文がチャンク化されている必要があります(HTTP/1.0—これについては後述します)。
Pingoraは、また、実際にはContent-Lengthを使用していませんでした(転送エンコーディングがRFCの規定によりContent-Lengthをオーバーライドしたため)。Transfer-Encodingが認識されず、HTTP/1.0バージョンであるため、リクエストボディは、代わりにクローズ区切りとして扱われました(つまり、レスポンスボディの終了は、基となるトランスポート接続の終了によってマークされます)。フレーミングヘッダーの欠如は、HTTP/1.0でも同じ誤解を引き起こす可能性があります。レスポンス本文はクローズ区切りにできますが、リクエスト本文は決してクローズ区切りにすることはできません。実際、この明確化は、RFC 9112で別の注記として明示的に言及されています。
これはHTTP/1.0転送エンコーディングを定義しないリクエストです。RFCでは、転送エンコーディングを含むHTTP/1.0リクエストは、「フレーミングに欠陥があるかのようにメッセージを扱って」接続を閉じる必要があると義務付けています。nginxやhyperなどのパーサーは、曖昧なフレーミングを避けるために、これらのリクエストを拒否するだけです。
攻撃者がHTTP/1.0ドメインの後に部分的なHTTPリクエストヘッダーを+ Transfer-Encodingリクエストでは、Pingoraはその部分的なヘッダーを別個のリクエストとしてではなく、同じリクエストの一部として誤って解釈します。これにより、時期尚早なアップグレードの例で説明したと同じ種類の非同期攻撃が可能になります。
これは、特にレスポンスとリクエストのメッセージのフレーミングという点で、RFCのより根本的な誤解を招くものです。それ以来、不適切な多重のTransfer-Encodingの解析を修正し、HTTPリクエストボディがクローズ区切りと見なされることがないように、リクエスト長のガイドラインに厳密に準拠し、不正なContent-LengthおよびHTTP/1.0 + Transfer-Encodingのリクエストメッセージを拒否しました。さらに、追加した保護には、デフォルトで拒否する CONNECTリクエストが含まれます。これは、HTTPプロキシロジックは現在、CONNECTアップグレードプロキシの目的でCONNECTを特別なものとして扱わないためであり、これらのリクエストには特別なメッセージフレーミングルールがあります。(受信のCONNECTリクエストはCloudflare CDNによって拒否されることに注意してください。)
当社のサービスを内部で調査・計測したところ、Pingoraサービスに到着したリクエストが誤って解釈されることはなかったと考えました。CDNのダウンストリームのプロキシレイヤーはHTTP/1.1のみとして転送し、無効なContent-Lengthなどの曖昧なフレーミングを拒否し、チャンク化されたリクエストに対しては、単一のTransfer-Encoding: chunkedヘッダーのみを転送することがわかりました。
この調査者は、デフォルトのCacheKeyの構築に関する別のキャッシュポイズニングの脆弱性も報告しています。素朴なデフォルト実装は、URI パスのみを考慮に入れており(ホストヘッダーやアップストリームサーバーのHTTPスキームなどの他の要素を含まず)、そのため、同じHTTPパスを使用する異なるホストが競合し、互いのキャッシュを汚染する可能性がありました。
これは、デフォルトのCacheKey実装を使用することを選択したアルファ版プロキシキャッシング機能のユーザーに影響を与えます。その後、このデフォルトは削除しました。HTTPスキーム + ホスト + URIのようなものを使用することは多くのアプリケーションにとって理にかなっていますが、ユーザーにはキャッシュキーを構築する際に注意を払っていただきたいためです。たとえば、プロキシロジックがアップストリームリクエストのURIやメソッドを条件付きに調整する場合、そのロジックもポイズニングを回避するためにキャッシュキースキームに要因を組み込む必要があります。
内部的には、Cloudflareのデフォルトのキャッシュキーは、キャッシュキーポイズニングを防止するために多くの要素を使用しており、以前に提供されていたデフォルトを使用することはありません。
Pingoraをプロキシとして使用する場合は、できるだけ早い段階でPingora 0.8.0にアップグレードしてください。
この脆弱性により、Pingoraユーザーに多大な影響を与えたことをお詫び申し上げます。PingoraがCloudflareを超える重要なインターネットインフラストラクチャとしての地位を確立するに伴い、厳格なRFCコンプライアンスの使用をデフォルトで促進することがフレームワークにとって重要であると考えており、今後もこの取り組みを継続していきます。フレームワークのユーザーは、Cloudflareと同じ「ワイルドインターネット」に悩まされる必要はほとんどないはずです。私たちの意図は、デフォルトで最新のRFC基準に厳格に準拠することで、Pingoraユーザーのセキュリティを強化し、インターネット全体をベストプラクティスに向けて移行することです。
- 2025年12月2日:バグバウンティ経由でアップグレードベースのスニッフィングが報告される。
- 2026年1月13日:転送エンコーディング / HTTP/1.0の解析に関する問題が報告されています。
- 2026年1月18日:デフォルトのキャッシュキー構築の問題が報告されました。
- 2026年1月29日から2026年2月13日:修正に関する報告者が確認済み。さらなるRFCコンプライアンスチェックに取り組みます。
- 2026年2月25日:キャッシュキーのデフォルトの削除と追加のRFCチェックがリサーチャーと検証済み。
- 2026年3月2日:Pingora 0.8.0をリリース
- 2026-03-04: CVEアドバイザリーを公開
レポート、詳細な複製、そしてバグバウンティプログラムを通じて修正を確認してくださったRajat Raghav氏(xclow3n)に感謝いたします。詳細については、研究者の対応するブログ記事をご覧ください。
また、Pingoraオープンソースコミュニティの積極的な関与、レポートの発行、フレームワークへの貢献に心からの謝意を表します。Cloudflareは、より良いインターネットの構築をサポートしてくれる存在です。