こんにちは!ネットワークの深淵を旅する皆さん、ようこそ。
今日は、Web通信の「お作法」であるHTTPの中でも、特に「トラブルの火種」になりやすいTransfer-Encoding(転送符号化)とContent-Length(コンテンツ長)の仲の悪さについてお話しします。
「ヘッダーが二つあると何が起きるの?」という素朴な疑問から、ネットワークの裏側で暗躍する「リクエストスマグリング」というサイバー攻撃の影まで、一緒に紐解いていきましょう。
—
荷物のサイズは誰が決める?:二つの配送ルール
Web通信を「郵便」に例えてみましょう。あなたがWebサイト(サーバー)にリクエストを送ることは、手紙を送るのと同じです。
通常、手紙には「この手紙は全部で100グラムありますよ」というContent-Length(中身の長さ)を書きますよね。受け取る側は「なるほど、100グラム受け取ったら封筒を閉じよう」と判断できます。
ところが、HTTP/1.1にはもう一つ、別のルールがあります。それがTransfer-Encoding: chunked(分割転送)です。
「ちぎって送る」というアイデア
例えば、巨大なファイルを送る時、全部用意できるまで待っていたら時間がかかりますよね。そこで、「まずは最初の塊(100バイト)を送るよ!次はまた送るから待ってて!」というふうに、荷物をバラバラにして送るのがこの「chunked」という仕組みです。
ここで問題が発生します。「荷物の総量(Content-Length)」と「バラバラ送る宣言(Transfer-Encoding)」が同時に書かれていたら、サーバーはどっちを信じればいいのでしょうか?
—
悪夢の始まり:解釈のズレが招く「スマグリング」
ネットワークの世界には、ユーザーとサーバーの間に「プロキシサーバー(中継役)」や「ロードバランサー(交通整理役)」が立っていることがよくあります。
ここで、「中継役はContent-Lengthを信じ、サーバーはTransfer-Encodingを信じる」といった「解釈のズレ」が起きると、とんでもないことが起きます。
リクエストスマグリングの仕組み
1. 攻撃者: 「100バイトのデータだよ(実際は200バイト送る)」という嘘のContent-Lengthと、Transfer-Encodingを混ぜて送る。
2. 中継役: 「ふむ、Content-Lengthが100バイトだから、ここまでが1通目の手紙だな」と判断してサーバーに転送する。
3. サーバー: 「Transfer-Encodingがあるから、最後まで読み切るぞ」と判断する。
4. 結果: サーバーの中に、「中継役が読み飛ばしたはずの残り100バイト」が、次のリクエストの「頭」として混入してしまう!
これが「HTTPリクエストスマグリング」です。前の人の荷物が、次の人の手紙に紛れ込んで届いてしまう……。これを使えば、他人のIDでログインしたり、管理者権限を盗み見たりできてしまう可能性があるのです。
—
実務で意識すべきポイント:どう防ぐ?
インフラエンジニアとして、この脆弱性を避けるために意識すべきは「曖昧さを排除する」ことです。
1. 二重設定を禁止する
現代の強力なWebサーバー(NginxやApacheなど)では、Content-LengthとTransfer-Encodingが共存している場合、エラーを返すか、どちらかを強制的に無視する設定が可能です。
Nginxの例:セキュリティ対策として、曖昧なリクエストを拒否する設定
不正なヘッダーが含まれる場合に400 Bad Requestを返す
if ($http_transfer_encoding ~ “chunked”) {
# chunkedが指定されている場合はContent-Lengthを無効化する処理を入れるなど
# 最近のバージョンでは自動で厳格化されています
}
2. 常に最新のミドルウェアを使う
HTTPの解釈ルールは、長年の攻撃と対策の歴史そのものです。最新のサーバーソフトは、こうしたヘッダーの競合に対して非常に厳格になっています。「昔のままで動いているから大丈夫」と思わず、定期的なアップデートが最大の防御です。
3. デバッグ時はパケットを覗く
もし「なんかリクエストが変な挙動をするな」と思ったら、Wiresharkなどのツールでパケットを見てみてください。
- Content-Length: 数値で書かれていますか?
- Transfer-Encoding: chunked と書かれていますか?
もし両方が混在していたら、それがトラブルの犯人である確率が非常に高いです。
—
まとめ:ネットワークは「信頼」でできている
今回お話しした「ヘッダーの解釈のズレ」は、まさに「人間同士のコミュニケーションのすれ違い」と同じです。「言ったつもり」「聞いたつもり」の間に、悪意ある隙間が生まれるのです。
HTTPプロトコルはシンプルですが、それゆえに解釈の余地が残されています。皆さんが現場でトラブルに遭遇したとき、「プロトコルの仕様書」だけでなく、「中継役とサーバーの間で、どう言葉が翻訳されているか?」を想像してみてください。
そうやって一歩ずつパケットの旅路を追っていくことで、皆さんは間違いなく「ネットワークの達人」へ近づいていきます。
それでは、また次回の深淵でお会いしましょう!
コメント