【実務・中級編】 HTTPリクエストスマグリング(CL.TE/TE.CL)の悪用と防御 – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

HTTPリクエストスマグリング:境界線の曖昧さを突く「見えない侵入」

現場でインフラやアプリを見ていると、「HTTP通信は標準化されているから安全だ」と盲信しているエンジニアによく出会う。だが、現実はそう甘くない。HTTPリクエストスマグリング(HRS)は、フロントエンドのプロキシサーバー(Nginx, HAProxy, AWS ALBなど)と、バックエンドのアプリケーションサーバーとの間で「リクエストの終わり」をどう解釈するかという解釈の不一致(Desync)を突く、極めて狡猾な攻撃だ。

これを食らうと、認証をバイパスされ、他人のセッションを奪取され、あるいはキャッシュポイズニングによってサイト全体を汚染される。今日は、この「見えない侵入」の正体と、現場で確実に防ぐための防衛術を叩き込む。

—

なぜ「解釈の不一致」が生まれるのか?

HTTP/1.1では、リクエストのサイズを判定するのに Content-Length (CL) ヘッダーと Transfer-Encoding (TE) ヘッダーの2つが使われる。

  • CL: ボディの長さをバイト数で指定する。
  • TE: チャンク形式でデータが送られることを示す。

攻撃者は、わざと両方のヘッダーを混在させ、フロントエンドとバックエンドで優先順位が異なることを悪用する。

1. CL.TE 攻撃(フロントはCL、バックはTE)

フロントが Content-Length を見てパケットを区切るのに対し、バックエンドが Transfer-Encoding を優先してチャンクの終わりまで待ち続ける場合、バックエンドのキューには「次のリクエストの一部」が残る。これが次のユーザーのリクエストと結合し、予期せぬ挙動を引き起こす。

2. TE.CL 攻撃(フロントはTE、バックはCL)

逆にフロントが Transfer-Encoding を正しく処理し、バックエンドが古い仕様や設定ミスで Content-Length を優先してしまうと、リクエストの切り出し位置がズレる。

—

実践的防御:設定とコードで塞ぐ

この脆弱性は、アプリのコードで直すというよりは、「境界の曖昧さを排除する」というインフラの設計思想で防ぐのが正解だ。

1. Nginxでの厳格なリクエスト制御

Nginxをフロントに置いている場合、不正なヘッダーを持つリクエストを門前払いするのが最も効果的だ。nginx.conf に以下の設定を加え、リクエストの解釈を厳格化せよ。

# nginx.conf の http ブロックに記述
# 不正なヘッダーが含まれるリクエストを遮断する
underscores_in_headers off; # 下線付きヘッダーを無効化
ignore_invalid_headers on;  # 不正なヘッダーを無視せずエラーにする

server {
    listen 80;
    # チャンク転送エンコーディングの挙動を制限
    # バックエンドへの転送時にリクエストを正規化して再構築する
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

2. バックエンドでのリクエストバリデーション(Node.js/Expressの例)

バックエンド側では、受け取ったリクエストのヘッダーが二重定義されていないかをチェックするミドルウェアを挟むのが鉄則だ。

// セキュリティミドルウェアの例
const validateHeaders = (req, res, next) => {
    // Content-Length と Transfer-Encoding が同時に存在する場合は拒否する
    if (req.headers['content-length'] && req.headers['transfer-encoding']) {
        console.error(`[SECURITY ALERT] 潜在的なスマグリング攻撃を検知: ${req.ip}`);
        return res.status(400).send('Bad Request: Ambiguous header definition.');
    }
    next();
};

app.use(validateHeaders);

—

根本解決:HTTP/2 への完全移行

ここまで対策を語っておいてなんだが、CLとTEの不整合問題は、HTTP/2へ移行することで根本的に消滅する。

HTTP/2はバイナリプロトコルであり、フレーム単位でデータ長が厳密に管理されるため、HTTP/1.1のような「ヘッダーで区切り文字を推測する」という脆弱な仕組みが存在しない。

もし君たちが管理しているシステムがまだHTTP/1.1主体なら、それは技術的負債であり、セキュリティ上のリスクだ。ロードバランサー側でHTTP/2を有効化し、バックエンドとの通信もなるべくHTTP/2に切り替えるロードマップを引くことを強く推奨する。

チーフエンジニアからのアドバイス

「動いているから大丈夫」という考えが、一番の脆弱性だ。
HRSの恐ろしいところは、ログには「正しいリクエスト」しか残らないケースが多いことだ。もし奇妙なエラーが頻発したり、セッションの混線が疑われるようなら、即座にプロキシサーバーのヘッダー処理設定を見直せ。

セキュリティとは、境界線をいかに明確に引くかの勝負だ。曖昧な処理を許すな。それが、システムを鋼鉄のように堅牢にする唯一の方法だ。

コメント

タイトルとURLをコピーしました