Apache mod_cache — Range リクエストによるキャッシュ汚染
リバースプロキシ構成の Apache + mod_cache で、キャッシュが空の URL への初回アクセスが HTTP Range リクエスト(206 Partial Content)だった場合、その断片だけをキャッシュしてしまい、以降その URL の「完全なキャッシュ」として配信してしまう問題。
発生条件
- Apache が対象バージョン(2.2 系は 2.2.22 以下/2.4 系は 2.3.5 以下)
- proxy 先のコンテンツが Range Request(Partial Content)に対応している
- proxy 先が
Cache-Control/Expiresを出力しない mod_cache+mod_rewrite+mod_proxy構成
再現(要旨)
初回に Range: bytes=0-3 で先頭 4 バイトだけ取得すると、その hell という断片がキャッシュされ、次の通常アクセスでも断片が「完全版」として返ってしまう。
curl -H 'Range: bytes=0-3' http://.../proxy/hello_world # → hell(これがキャッシュされる)
curl http://.../proxy/hello_world # → hell(断片が完全版として配信される)
影響
攻撃者が任意 URL のキャッシュを「壊れた断片」で先に作れてしまうため、正規のコンテンツを表示させない サービス不能(DoS) になりうる。CDN のように共有キャッシュを挟む構成では影響が大きい。
補足
本家では 2.2.23/2.3.6 で「206 応答はキャッシュしない」よう修正済み(CVE として処理されたものではなく、挙動変更として入った)。見つけたのは 2013 年末で、翌 2014 年に再現手順つきで gist として公開した。詳しい設定と全手順は当時の gist(gist.github.com/kimoto/6b347dfbaa9f6a87c0c7)に残っている。