はじめに
こんにちは!株式会社エーアイセキュリティラボ 開発チームです。
我々はAeyeScanという クラウド型Webアプリケーション脆弱性検査ツールの開発をしています。
4月20日に、「Apache httpdの脆弱性(CVE-2024-27316)」という脆弱性を検出する機能を追加しました。この機能は「HTTP/2 CONTINUATION Flood」と呼称されるDoSの脆弱性を、対象サイトに負荷を与えること無く、検出することができます。今回はこの脆弱性の周知のために、脆弱性の概要と実際にApache httpdをどのように攻撃するのかを解説します。
HTTP/2 CONTINUATION Flood
HTTP/2 CONTINUATION Floodは、HTTP/2サーバに対するDoSの脆弱性です。
元をたどると、1月15日に、HackerOneというバグバウンティのプラットフォームで、Node.jsに対して最初の報告が行われたようです。
https://hackerone.com/reports/2319584
その後4月3日に、発見者により、詳細な解説記事が公開されています。
https://nowotarski.info/http2-continuation-flood-technical-details/
この解説記事では、この脆弱性は、1台のマシンで、アクセスログに痕跡を残すこと無く、サーバをクラッシュさせることができる、と書かれており、危険性が強調されています。
また日本では、4月9日にJVNに掲載され、翌日にはIT系のニュースサイトにも掲載され、話題となりました。
https://jvn.jp/vu/JVNVU99012560/
https://forest.watch.impress.co.jp/docs/news/1583044.html
この脆弱性は、複数のミドルウェアのHTTP/2サーバ機能が影響を受けます。ミドルウェアごとに以下のCVEが割り当てられています。
影響を受けるミドルウェア | CVE番号 |
---|---|
Node.js HTTP/2 server | CVE-2024-27983 |
Envoy HTTP/2 codec | CVE-2024-27919, CVE-2024-30255 |
Tempesta FW | CVE-2024-2758 |
amphp/http | CVE-2024-2653 |
Go net/http および net/http2 | CVE-2023-45288 |
nghttp2 | CVE-2024-28182 |
Apache httpd | CVE-2024-27316 |
Apache Traffic Server | CVE-2024-31309 |
影響を受けるミドルウェアを使用している場合は、対策済みのバージョンに更新する必要があります。
攻撃方法
HTTP/2 CONTINUATION Floodの攻撃方法は非常にシンプルです。
HTTP/2の通信では、1つのTCPコネクション内で複数のストリーム(リクエスト・レスポンスのペア)を同時に送信できます。実際の通信では、ストリームのデータは、フレームと呼ばれる単位に分割され、フレームの並びとして送信されます。例えば、リクエストヘッダを送信する場合は、HEADERSフレームを送信し、次にリクエストボディを送信する場合は、DATAフレームを送信します。
また、HTTP/2の仕様として、ヘッダのサイズが大きい場合に、HEADERSフレームを分割して送信することが認められています。その際に利用されるのがCONTINUATIONフレームです。分割して送信する場合、
1. HEADERSフレーム
2. CONTINUATIONフレーム
3. CONTINUATIONフレーム
…
n. 最後のCONTINUATIONフレーム
という順で送信することができます。
今回のHTTP/2 CONTINUATION Floodの脆弱性は、このCONTINUATIONフレームを利用して大量のリクエストヘッダを送信した場合に、ミドルウェアがヘッダを過剰に受信してしまうことが原因で発生しています。つまり、CONTINUATIONフレームで大量のリクエストヘッダを送ると、サーバがクラッシュする、というシンプルな攻撃方法です。
また、PoCも公開されています。ただし、機能しないと思われるものも含まれるため、利用の際は注意してください。
Envoy HTTP/2 codec
https://github.com/blackmagic2023/Envoy-CPU-Exhaustion-Vulnerability-PoC
Apache httpd
https://github.com/lockness-Ko/CVE-2024-27316
Go net/http および net/http2
https://github.com/hex0punk/cont-flood-poc
Node.js HTTP/2 server
https://github.com/lirantal/CVE-2024-27983-nodejs-http2
Apache httpd (CVE-2024-27316)の場合の攻撃方法
Apache httpdは、Webサーバとして一般によく利用される製品であるため、CVE-2024-27316は弊社でも優先的に調査を行いました。
CVE-2024-27316はCVSS v3スコアが7.5、深刻度がHighに該当する脆弱性です。
https://access.redhat.com/security/cve/CVE-2024-27316
影響を受けるバージョンは2.4.58以下、修正バージョンは2.4.59です。脆弱性についてはApache HTTP Server 2.4 vulnerabilitiesのページに記載があります。
moderate: Apache HTTP Server: HTTP/2 DoS by memory exhaustion on endless continuation frames (CVE-2024-27316)
HTTP/2 incoming headers exceeding the limit are temporarily buffered in nghttp2 in order to generate an informative HTTP 413 response. If a client does not stop sending headers, this leads to memory exhaustion.
修正パッチは以下のコミットです。
https://github.com/apache/httpd/commit/0d73970ec161300a55b630f71bbf72b5c41f28b9
このコミットは、ヘッダの解析時にエラーが100回より多く発生したら、解析をやめる、という内容のようです。
“CVE-2024-27316 exploit”でWeb検索すると https://github.com/lockness-Ko/CVE-2024-27316 のPoCが見つかります。PoCのソースを読むと、大量のスレッドで
ヘッダ名:
aaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfg%d
ヘッダ値:
iiiiiiiiiiiaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfgaaaaaouiehjbrbfg%d
(末尾の%dは毎回異なる数字に置換される)
というヘッダをCONTINUATIONフレームで送り続ける、というシンプルな実装だとわかります。ただ、このPoCは、手元で検証した限り、修正前後のバージョンで挙動に差が出ませんでした。いずれのバージョンも、メモリが一時的に増加しますが、その後収まりました。
また、適当なヘッダ(“x-hoge: 1”など)をCONTINUATIONフレームで大量送信するコードを自作してみましたが、サーバの負荷はわずかに増加する程度でした。同じ値を利用していることが良くないのかと思い、ヘッダ名やヘッダ名を毎回変えてみても同様でした。
仕方なくApache httpdのソースを調査したところ、色々と条件があることがわかりました。まず、
https://github.com/apache/httpd/blob/c3ad18b7ee32da93eabaae7b94541d3c32264340/modules/http2/h2_stream.c#L757-L761
にある通り、ヘッダが100個を超えると解析処理がスキップされます。また、
https://github.com/apache/httpd/blob/c3ad18b7ee32da93eabaae7b94541d3c32264340/modules/http2/h2_stream.c#L800-L804
にある通り、ヘッダは最大200個までしか受け付けず、これを超えるとストリームがリセットされます。つまり、ヘッダの解析処理を繰り返し実行させるには、ヘッダとして受理されないようにする必要があります。これは実は簡単で、1つのヘッダの上限サイズより長いヘッダを送信すればよいだけです。1つのヘッダの上限サイズは
https://github.com/apache/httpd/blob/c3ad18b7ee32da93eabaae7b94541d3c32264340/include/httpd.h#L198
にある通り、8190です。この他にも、動作確認により、ヘッダの値ではなく、ヘッダ名を長い値にすることがメモリ枯渇を引き起こすために有効であるとわかりました。
これらの条件を元にして、ヘッダ名の長さ8190にして大量に送信すると、脆弱性のあるバージョンではメモリ使用率が100%付近まで到達することを確認できました。
また、修正バージョンではこの事象が発生しないことを確認できました。修正パッチは、このヘッダサイズのエラーが頻発したら解析をやめる、という内容だったようです。
検証に使用した環境とコードは以下で公開しています。
https://github.com/aeyesec/CVE-2024-27316_poc
まとめ
今回はHTTP/2 CONTINUATION Floodの脆弱性について概要を解説しました。また、Apache httpdに対して実際に攻撃を行い、メモリ使用率が100%付近に到達することを確認しました。
今回の検証により、攻撃方法がシンプルでも、Apache httpdの場合、実際に攻撃するためにはカスタマイズが必要となる、ということがわかりました。また、記事には書いていませんが、Node.jsにおいても、CONTINUATIONフレームを大量送信するだけでは攻撃が成立しないことを確認しています。他のミドルウェアも同様の可能性があります。そのため、当初の印象ほど簡単に攻撃できるというわけでは無いかもしれません。しかしながら、危険な脆弱性であることに変わりはありません。これらのミドルウェアを使用している場合は、早急に修正バージョンへのアップデートを行うことを推奨します。
おわりに
AeyeScanはSaaS型のWebアプリケーション脆弱性診断プラットフォームです。かんたんに高精度なWeb診断を実施することができることから、Webアプリ診断の内製化ツールとして多くの企業様にご活用いただいております。
今回解説したApache httpdの脆弱性(CVE-2024-27316)もサーバに負荷を与えることなく検出することができます。ご興味ある方はぜひトライアルにてお試しください。
AeyeScanの詳細はこちら: https://www.aeyescan.jp