HTTP/2・HTTP/3の「盲点」:ヘッダー圧縮攻撃(HPACK/QPACK)からサーバーを守り抜く技術
現場でインシデント対応をしていると、多くのエンジニアが「TLSさえかけていればWeb通信は安全だ」という幻想を抱いていることに気づかされます。しかし、現代の攻撃者はアプリケーション層の脆弱性など突きません。彼らが狙うのは、「プロトコルそのものの実装の歪み」です。
今日は、HTTP/2のHPACK、そしてHTTP/3のQPACKに潜む「ヘッダー圧縮攻撃」について、現場の知見を共有します。教科書的な解説は省略します。泥臭い防御の実装方法に直行しましょう。
—
なぜ「ヘッダー圧縮」が攻撃の入り口になるのか
HTTP/2以降、通信効率を上げるためにヘッダーを圧縮して送る仕組みが導入されました。これがHPACK(H2)やQPACK(H3)です。
攻撃者は、この「圧縮テーブルの更新」を悪用します。具体的には、細工されたヘッダーを大量に送り込み、サーバー側のメモリを強制的に確保させる、あるいはCPUを枯渇させる(DoS攻撃)手法です。
特に恐ろしいのは、これがWAFのシグネチャをすり抜ける点です。WAFは「リクエストボディ」や「URLパラメータ」は監視しますが、プロトコルのコンテキスト内で完結する圧縮テーブルの操作までは、標準設定では見ていないことが多いからです。
—
防御の鉄則:リソース制限という名の「防波堤」
この攻撃に対する唯一にして最強の防御は、「サーバーが受け入れるヘッダーの最大サイズと、テーブル更新量の上限を厳格に制限すること」です。
Nginxでの防御設定(鉄板構成)
NginxでHTTP/2を運用しているなら、`nginx.conf`に以下の制限を必ず入れてください。これを入れないのは、玄関の鍵を開けっ放しで外出するのと同じです。
http {
# ヘッダーフィールドの最大サイズを制限(デフォルトは大きすぎる場合がある)
large_client_header_buffers 4 8k;
# HTTP/2 接続ごとの設定
http2_max_header_size 16k; # ヘッダーの合計サイズを16KBに制限
http2_max_requests 1000; # 1接続あたりのリクエスト数を制限し、リソースの占有を防ぐ
# 攻撃者は大きなテーブルサイズを要求してメモリを枯渇させるため、
# 適切に上限を設ける(HPACK圧縮テーブルの制限)
# ※nginxのバージョンにより設定項目が異なるため、最新のドキュメントを確認すること
}
—
Node.js (Fastify/Express) でのヘッダーバリデーション
Node.jsでサーバーを構築している場合、HTTP/2モジュールで接続を扱う際は、ヘッダーのサイズをアプリケーション層でも監視するのが賢いやり方です。
// Fastifyでの例
const fastify = require(‘fastify’)({
http2: true,
// 最大ヘッダーサイズをバイト単位で指定
maxParamLength: 2000,
onSend: (request, reply, payload, next) => {
// リクエストヘッダーのサイズを独自にチェックするミドルウェア的処理
const headerSize = JSON.stringify(request.headers).length;
if (headerSize > 16384) { // 16KBを超えたら拒否
return reply.code(431).send(‘Request Header Fields Too Large’);
}
next();
}
});
—
攻撃者視点:PoCの考え方とリスク管理
攻撃者は、Pythonの`h2`ライブラリなどを使い、意図的に「圧縮テーブルを更新させるヘッダー」を連続して送りつけます。
- リスクの正体: サーバー側でテーブルのデコード処理がループし、CPU使用率が100%に張り付きます。さらにメモリが解放されないまま新しいリクエストが次々と積み上がり、最終的にOOM Killer(Out of Memory)によってプロセスが落ちます。
- 現場の教訓: この手の攻撃は、監視ツールで「CPUスパイク」として検知できます。しかし、アラートが鳴った時にはすでにサービスはダウンしています。だからこそ、「設定による未然防止(Preventive Control)」が何よりも重要なのです。
—
セキュリティチーフからの提言
HTTP/3(QUIC)の導入を検討しているチームも多いでしょう。QPACKはHPACKの反省を活かして設計されていますが、依然として「ストリームごとのリソース消費」という課題は消えていません。
1. デフォルト値を信じるな: NginxやEnvoyのデフォルト設定は「利便性」のために緩めに設定されています。商用環境では必ず「最も厳しい設定」から始め、必要に応じて緩和してください。
2. CDNの活用: 自前でプロトコルスタックを堅牢にするのが難しいなら、CloudflareやFastlyのような、最新のプロトコル攻撃に対するシグネチャを常時更新しているCDNの背後に隠れるのが、最も費用対効果の高い戦略です。
3. 可視化の徹底: Prometheus等で、HTTP/2の接続数やヘッダーサイズの分布を監視してください。異常なサイズのヘッダーが飛んできていないか、グラフが一瞬でも跳ねていないかを確認するだけで、攻撃の予兆を掴めます。
エンジニアの皆さん、プロトコル層のセキュリティは地味ですが、ここを固めることは「システムの心臓部を守ること」と同義です。今日紹介した設定、今すぐ確認してみてください。それが、あなたのシステムを明日救うかもしれません。

コメント