改行コードに要注意! HTTP ヘッダインジェクションの概要と対策
HTTP ヘッダインジェクション (HTTP Header Injection)は、ユーザーから受け取ったデータを Web アプリケーション側で適切にチェックせずに、HTTP レスポンスヘッダに反映させてしまうことで発生する脆弱性・攻撃手法です。
改行コードが起因となることから、CRLF インジェクション(CRLF Injection)とも呼ばれています。
本記事では HTTP ヘッダインジェクションの概要と発生する仕組み、対策方法について、主に Web 開発者に向けてわかりやすく解説していきます。
HTTP ヘッダインジェクションとはなにか
HTTP ヘッダインジェクションは、ユーザーがフォームや URL で入力するリクエストパラメーターやクエリパラメーターを、想定しないデータに改変して送信することで、HTTP レスポンスヘッダに新たなヘッダ要素を追加したり、レスポンスボディに任意の文字列を追加することができる脆弱性および攻撃手法です。
類似の脆弱性として「クロスサイトスクリプティング(XSS)」が挙げられますが、違いとしては攻撃者が細工されたデータを仕込む起点と場所が異なります。
とはいえ、レスポンスボディに任意の文字列を追加できてさえしまえば、攻撃者は任意のコンテンツが埋め込めるという意味では、クロスサイトスクリプティングと同等か、それ以上の脅威になる脆弱性と言えるでしょう。
HTTP ヘッダインジェクション攻撃でどんな影響が出るのか
HTTP ヘッダインジェクションによって引き起こる影響としては、以下のようなものが考えられます。
- 悪意ある Web ページ(フィッシングサイト等)へリダイレクト(誘導)されてしまう
- 任意の Cookie が生成できてしまうことで、セッション ID が固定されてしまう
- 任意の HTTP レスポンスボディが生成されることで、Web ページに表示され内容が改ざんされて表示されてしまう、不正な JavaScript が実行されてしまう
- ユーザー単位での DoS(サービス提供妨害)攻撃(Cookie Bomb 攻撃)
攻撃者の視点では、ヘッダインジェクション自体は 1 つのきっかけであり、別の脆弱性にアクセスするための手段であったり、Web アプリケーションをさらに攻撃するための 1 つの方法にしかすぎません。
HTTP ヘッダインジェクションを通してデータを挿入できた場合、攻撃者は次の打ち手として、Referer ヘッダや Cookie の値を用いて、機微情報の盗難やクロスサイトスクリプティング攻撃、セッションフィクセイション攻撃(セッション固定化攻撃)を仕掛ける可能性があります。
HTTP ヘッダインジェクションが起きる原因
HTTP ヘッダインジェクションが起きる原因として、ユーザーが入力したデータの中に「改行コード(CR 文字 \r 、LF 文字 \n )」が含まれていることが挙げられます。
HTTP の仕様では、レスポンスヘッダ 1 行につき 1 つの意味を持つため、Web アプリケーション側で改行コードの処理が適切に行えていないと、意図しないレスポンスヘッダが追加できることになるのです。
HTTP ヘッダインジェクションが発生する例
それでは一例を見ていきましょう。
Web アプリケーションの開発においてよくあるユースケースとして、Web ページの移転や統廃合によって、ユーザーが入力した文字列を含めた新しい URL へリダイレクトしたいというケースです。
この場合、レスポンスヘッダに Location: (移動先の URL) を付加することで機能を実現することになるかと思います。
HTTP ヘッダインジェクション脆弱性がある Web アプリにおいて攻撃者が意図した Cookie をセットする流れ
上記の図のケースでは、redirect.php にアクセスすると index.php?to=home へリダイレクトする挙動となりますが、よく見ると to クエリパラメーターに %0d%0a が含まれています。
これが改行コード(CRLF 文字)を URL エンコードした文字列となり、改行を意味します。
本来であればクエリパラメーターの to=home という文字列だけあれば十分であり、改行コード以降の文字列は除去すべきものです。
しかし、脆弱な Web アプリケーションの場合、改行コードによって後続文字が一つの HTTP ヘッダの行と解釈され、 Set-Cookie レスポンスヘッダが新たに生成されることになります。
今回の場合では、アクセスした Web ブラウザの Cookie 内に SID=abcd1234 が記録されてしまいます。
SID をセッション ID として扱う Web アプリケーションでは、セッション ID が abcd1234 に固定化されることで、セッションの乗っ取り・なりすましが行える可能性が発生します。
Cookie の固定によるセッション固定攻撃(Session fixation)
先ほどの例で、Set-Cookie をヘッダとして挿入することで、被害者に対して任意の Cookie を設定・固定化させられるということがわかりました。
この攻撃手法は一般的には「セッション固定化攻撃(Session fixation)」と呼ばれています。
セッション固定攻撃は、アプリケーションが設定する「ユーザが誰であるかを特定するための Cookie」を、攻撃者が任意の値で設定するところから攻撃が始まります。
被害者となるユーザは、知らないうちに設定されたセッション用の Cookie を用いて、サービスに対してログインを行います。
すると、サービス側は「(細工された)Cookie の持ち主は、被害者 A さんだ」と記録します。
そして、攻撃者は頃合いを見て、被害者 A さんに設定した Cookie を自身のブラウザに設定します。
こうすることで、攻撃者は、(ログイン済みの)被害者 A さんに設定させた Cookie を使って、なりすましによる不正ログインが成功します。
Cookie Bomb 攻撃によるユーザ単位の DoS
Cookie を強制設定できると、場合によっては不正ログインに繋がるということを理解いただけたと思いますが、問題はそれだけではありません。
Cookie を強制設定できる場合、そのユーザが対象サービスを利用できなくすることができる Cookie Bomb 攻撃を仕掛けられる場合があります。
Cookie Bomb 攻撃は、被害者の Cookie にとても大きな Cookie 値を設定させることで、サービス側の Cookie 受け付け上限値を超えさせるという攻撃です。
仮に Cookie の受け付け上限容量より大きいデータが送られてきた場合、それを受け取るミドルウェアなどの設定にもよりますが、そのリクエストを 400 Bad Request などのレスポンスで拒否します。
Apache Http Server では、デフォルトだと 8190 バイト以上の Cookie 値が送られるとそのリクエストを拒否します。
Nginx だと 8 キロバイトが上限値となっています。
このように、大きな Cookie を被害者に設定させることができる場合、全てのリクエストに大きな Cookie が紛れ込むため、サーバ側はそれらのリクエストを全て拒否することに繋がり、ユーザ単位の DoS が成立します。
この攻撃の厄介なところは、被害者側で問題を検知したり、対応をすることが困難な点にあります。
仮に大きな Cookie が設定された場合、被害者はブラウザから Cookie を消去することでしか、問題を解消できなくなります。
しかし、レスポンスには 400 Bad Request などとしか表示されないため、被害者側では原因を特定できないと言う問題に陥ります。
どうやって HTTP ヘッダインジェクション対策を行えばよいか
HTTP ヘッダインジェクションの対策としては、ユーザーが入力したデータをサーバーのレスポンスヘッダに含めないことが重要になります。
本当にユーザーが入力したデータをレスポンスヘッダに入れるべきなのか、入れなくても同等の機能を実現できないか、仕様面の見直しを検討してください。
実装上レスポンスヘッダに入れないといけない明確な理由があり、やむを得ない場合は、すべての文字列の改行コード(いわゆる CR 文字 と LF 文字)をチェックし、改行コードをはじめとした制御文字を受け入れないようにバリデーション処理を施す必要があります。
どうしてもユーザーが入力したデータを扱いたい場合でも、一般的なユースケースとしては英数字の短い文字列が受け付けられれば十分な場合が多いです。
そのため、実装時は厳格なホワイトリスト方式によるバリデーションを行うことをお勧めします。
加えて、HTTP ヘッダを文字列として直接出力する実装を行うと、この脆弱性は発生しやすいといえます。(たとえば PHP であれば header() 関数を使って直接出力を行う場合は注意が必要です)
昨今の Web アプリケーションでは、フレームワーク側で HTTP レスポンスヘッダを出力するための専用 API やメソッドが用意されていることが一般的ですので、これを用いて出力することを検討してください。
さいごに
今回は HTTP ヘッダインジェクションと呼ばれる脆弱性・攻撃手法についてご紹介いたしました。
HTTP ヘッダインジェクションの影響を受ける Web アプリケーションは、HTTP 仕様の改訂、ミドルウェア側の対応により減りつつありますが、脆弱な Web アプリケーションである場合は次の攻撃の一手を攻撃者に与えてしまうため、油断できない脆弱性といえるでしょう。
また、HTTP ヘッダインジェクション自体には対処できたとしても、現在利用しているフレームワークやライブラリの内部に別の脆弱性が発見されるケースも多いにあります。
これらの脆弱性を把握するには、定期的にライブラリなどの棚卸しや脆弱性の発行状況をウォッチしていく必要があります。
yamory は、これらの OSS ライブラリの脆弱性利用状況を可視化し、脆弱性をスキャンすることができるツールとなっております。
もし興味がございましたらぜひ無料トライアルをお試しください。