curl 8.23.0で修正されたHTTP/2のUAF脆弱性CVE-2026-92392
目次
TL;DR
影響 curl / libcurl 8.12.0〜8.22.0のHTTP/2アップロード。深刻度High(条件付きRCEの可能性)
対応 curl 8.23.0以降への更新、または各ディストリビューション提供の修正パッチ適用
暫定 信頼できないサーバーへのアップロードでHTTP/2を避ける(--http1.1 指定など)
2026年10月14日、データ転送ツールcurlの最新版8.23.0が公開された。
通常の8週間リリースサイクルを2週間早めて6週で公開した理由は、HTTP/2のアップロード処理に存在する深刻な脆弱性CVE-2026-92392への対応にある。
この問題は単体の curl コマンドだけでなく、無数の言語やアプリケーションの通信基盤として組み込まれている共有ライブラリ libcurl にも同様に影響する。
curlプロジェクトでは深刻度の評価に独自の4段階(Low、Medium、High、Critical)を採用しているが、今回のCVE-2026-92392にはHighが割り当てられた。
プロジェクトがHighと判定したのは2021年以降で3件目にとどまる。
単なるサービス妨害(DoS)だけでなく、悪意あるサーバーからの通信によってクライアント側で任意のコードを実行できる可能性が検証で証明されたためHighの評価になった。
RST_STREAM 処理で残るダングリングポインタとヒープ上書き
今回の不具合は、HTTP/2が持つ単一の接続内で複数の通信を並行処理する多重化の仕組みと、curl内部の転送管理構造のライフサイクルのズレから生じている。
libcurlでは転送ごとに easy handle(struct Curl_easy)と呼ばれる1件ごとの通信管理構造体を作り、全体を管理する multi handle が並行転送を処理している。
問題は、クライアントがHTTP/2経由でサーバーへデータをアップロードしている最中に起こる。
悪意あるサーバーがウィンドウサイズ(受信可能なデータ量)を0にしてデータ送信を止め、レスポンスの一部を返した直後に、エラー理由として HTTP_1_1_REQUIRED または REFUSED_STREAM を指定したストリーム切断フレーム RST_STREAM を送りつける。
このフレームを受けると該当ストリームの転送は終了するが、物理的なTCP接続自体は切断されずに維持される。
このとき、curlは転送を終了状態に遷移させるものの、内部で該当する easy handle を指すポインタが無効化されないまま残り、ダングリングポインタが生じる。
呼び出し元アプリケーションは転送エラーを検知して easy handle を解放(free)する。
その直後に multi handle の破棄処理が進むと、libcurl内部の状態の食い違いからダウンロード用のメモリを確保しようとする。このとき、解放直後の easy handle と同じヒープ領域が再割り当てされ、サーバーから受信したデータがそのまま書き込まれる。
ASLR回避から関数ポインタ改ざんに至るRCEの前提条件
解放後使用によってデータ書き込みが発生した際、悪用手順ではまずクライアント内部のメモリアドレス情報がサーバー側へ流出する。
メモリ配置を起動ごとに分散させるASLRが有効な環境でも、この情報漏洩によってオフセットを計算できるようになる。
サーバーが偽の構造体データを流し込み、その中にある関数ポインタを改ざんした状態でlibcurlが該当処理を呼び出すと、攻撃者が指定した命令へ実行が移り、クライアント側で遠隔コード実行(RCE)が成立する。
ただし、PoCで示された成立条件は極めて限定的だ。
攻撃を成立させるには、クライアントが正規のTLS証明書を持つ攻撃者サーバーに対して約135KB前後のデータをアップロードしなければならない。
さらに、攻撃対象のcurlの正確なビルド構成やアーキテクチャ、libcのメモリアロケータ(glibc等のヒープ管理挙動)が完全に特定できており、OpenSSLのTLS 1.3セッションチケット処理やnghttp2内部で確保されたメモリが攻撃側の計算どおりに配置されている必要がある。実行できるコマンドの長さも約23バイト程度と非常に短い。
このメモリ配置やタイミングを1つでも満たさなかった場合、関数ポインタの呼び出しは不正メモリアクセスとして検知され、プロセスがクラッシュする。
実環境で無差別に悪用を成功させることが極めて困難なため、curl開発チームは今回の深刻度をCriticalではなくHighと判定した。
AIスキャナーによる検出と協調開示
この脆弱性は、Anthropicの研究者ルナ・トン(Luna Tong)氏が発見し報告した。
AIモデルを活用した新しいオープンソース向けセキュリティスキャナーを用いて検出され、完全に再現可能なDockerイメージとPoCを添えてcurlプロジェクトへ提出された。
以前取り上げた SQLiteに存在しない関数を突いた偽CVE群 では、LLMの幻覚をもとに実在しないコードや行番号を並べた架空の脆弱性報告が量産され、検証されないままデータベースに登録される事態が発生していた。
それに対して今回の事例は、AIを活用した検査ツールが、人間でも発見が難しい複雑なプロトコル状態遷移とメモリ管理の欠陥を検出し、動作する検証環境を構築して開発元へ協調開示された。
curlリーダーのダニエル・ステンバーグ(Daniel Stenberg)氏も、報告内容と再現コードの精度の高さを公式ブログで評価している。
C言語のメモリ安全性とRust移植を採用しない理由
共通脆弱性タイプCWE-416(解放後使用)に分類される今回の問題について、ステンバーグ氏は「C言語を採用していなければ避けられた可能性が高い不具合」と率直に認めている。
ポインタの参照管理を開発者の規律に依存するC言語では、HTTP/2のように非同期・並行で多数のストリームが生成・破棄されるプロトコルの実装において、この種の見落としや解放漏れを防ぎきれない。
しかしステンバーグ氏は、curlをRustなどのメモリ安全言語で書き直す選択肢を明確に否定している。
curlは30年近くにわたり、数百のオペレーティングシステムと数十のCPUアーキテクチャ上で動作するように改良されてきた。
現時点でこれだけのプラットフォームに対応できる代替言語は見当たらず、コードベースの移植は開発速度を落として新たな問題を招くだけだとステンバーグ氏は指摘している。
そのためcurlプロジェクトでは、メモリの直接アドレスをポインタとして保持するのをやめて、通信ごとに割り振る転送識別子(Transfer ID)を必要時に検索する設計への移行など、内部リファクタリングを継続する方針をとっている。
影響を受けるバージョンとアップグレード手順
CVE-2026-92392の影響を受けるのは、curlおよびlibcurlのバージョン8.12.0から8.22.0まで。
8.12.0未満のバージョン、および今回修正された8.23.0以降はこの影響を受けない。
長期保守されている旧ブランチに対しても、8.20.2(8.20.X系)、8.16.2(8.16.X系)、8.14.3(8.14.X系)などの修正版が提供されている。
根本的な対策はバージョン8.23.0以降へのアップデート、あるいは各OSディストリビューションから提供される修正パッチの適用だ。
即座のバージョンアップが難しい環境では、信頼できない外部サーバーへのアップロード処理でHTTP/2の利用を避けるか、--http1.1 オプションなどでHTTP/2ネゴシエーションを無効化して対処できる。
なお、--http1.1 はコマンドラインツールcurlでの回避策だ。libcurlを組み込んでいるアプリケーションでは、CURLOPT_HTTP_VERSION を CURL_HTTP_VERSION_1_1 に指定するなどの対応、または共有ライブラリ自体の更新が必要になる。