MBSD寺田さんの記事「LWSとHTTPヘッダインジェクション」では、PHPのheader関数に関連して、PHP側のHTTPヘッダインジェクション対策を回避する手法と、それに対するPHP側の対応について書かれています。この記事では、寺田さんの記事を受けて、現在でもHTTPヘッダインジェクション攻撃が可能なPHP環境が残っているかを検証します。
HTTPヘッダインジェクションとは
以下の様なスクリプトがあるとします。オープンリダイレクタ脆弱性がありますが、それは気にしないとして、PHP5.1.1までのバージョンでは、以下の様な攻撃が可能でした。<?php header('Location: ' . $_GET['url']);
http://example.jp/header.php?url=http://example/top.php%0d%0aSet-Cookie:+PHPSESSID%3DABC
すなわち、HTTPヘッダとして出力されるパラメータに改行を含めることにより、開発者の意図しないレスポンスヘッダを出力させることができるというものです。上記の例では、Set-Cookieヘッダを出力させることにより攻撃者が任意のセッションIDをセットさせ、セッション固定攻撃に悪用できるというケースを示しています。Location: http://example/top.php Set-Cookie: PHPSESSID=ABC
PHP 5.1.2での改良およびその抜け道
これに対して、PHP5.1.2にて、header関数の引数中の改行をチェクし、複数のヘッダを送信しないように改修されました。これで、PHPでヘッダインジェクションはできなくなった…と思いきや、抜けがありました。PHP5.1.2での修正は、改行を構成するキャリッジリターンとラインフィードのうち、ラインフィードのみをチェックしていて、キャリッジリターンはチェックしていません。一方、大半のブラウザ(IE、Google Chrome、Safari、Opera)ではキャリッジリターンのみでも改行とみなしていて、ヘッダインジェクションが可能な状態でした。
http://example.jp/header.php?url=http://example/top.php%0dSet-Cookie:+PHPSESSID%3DABC
この問題はPHP 5.3.11およびPHP 5.4.0で修正され、最新のPHPではキャリッジリターンのみを使ったヘッダインジェクションはできなくなっています。「継続行」を用いた攻撃方法
これでPHPではヘッダインジェクション攻撃はできなったと思われていましたが、まだ抜けがありました。それは継続行を使う方法です。継続行とは、HTTP/1.1のRFC2616で規定されていたもので、以下のように、一つのレスポンスヘッダを複数行に分けて記述するものです。行頭に空白やタブがある場合、それは直前のヘッダに継続する内容(継続行)とみなされます。
上の例では、Set-Cookieヘッダのdomain属性とpath属性を継続行に置いています。Set-Cookie: PHPSESSID=UJqaktGaFBGTTAyM0diNks1aEJvZ2NNYz; domain=example.jp; path=/;
これについて、下記の状況がありました。
- PHPは5.1.2で複数行ヘッダを禁止したが、継続行は正規のヘッダとして認めていた
- 多くのブラウザは継続行に対応していたが、IEのみ継続行を無視し、別のヘッダとして認識する
http://example.jp/header.php?url=http://example/top.php%0d%0a%20Set-Cookie:+PHPSESSID%3DABC
ご覧のように、改行(%0d%0a)につづいて空白(%20)を用いることにより、以下の状況によりヘッダインジェクション攻撃を行うものです。- PHPは継続行と認識してそのまま通す
- IEは(継続行ではなく)2つのヘッダと認識してSet-Cookieが受け入れられる
- 5.4.38
- 5.5.22
- 5.6.6
Linuxディストリビューションの対応
PHP本家の最新版ではHTTPヘッダインジェクションに対処されたといっても、CentOSやDebian等LinuxディストリビューションのパッケージとしてPHPを導入している環境ではどうでしょうか?以下のディストリビューションにて検証してみました。現時点のすべてのパッチを適用した状態でテストしています。- Centos 5、6, 7
- Ubuntu 10.04, 12.04, 14.04, 15.04, 15.10
- Debian 6, 7, 8
- Fedora 20, 21, 22, 23
この結果から言えることは…
- 全てのディストリビューションにおいて、キャリッジリターンのみによるヘッダインジェクションは対策されている
- 長期サポートのCentOS、Ubuntu LTSでは、継続行によるヘッダインジェクションにはパッチが提供されていない
※ 2016年8月11日のコミットにて、Ubuntu 12.04LTS以降も、継続行を禁止するパッチが作られました。これで、継続行によるヘッダインジェクションが可能なディストリビューションは、RHEL/CentOSのみとなりました。(2016年12月17日追記)
まとめ
HTTPヘッダインジェクションの最新動向について、寺田さんのブログ記事を参照しながら紹介しました。PHPの最新版においてはHTTPヘッダインジェクション攻撃の変種についても対策されているものの、CentOSやUbuntu等の長期サポートディストリビューションの中には、まだ「継続行」を用いた攻撃に対するパッチが提供されて環境があります。したがって、HTTPヘッダインジェクション脆弱性対策については、一応はPHP側の責任と考えたうえで、アプリケーション側でもヘッダ文字列のバリデーション等で対策をしておくことを推奨します。
PHPにおいて、HTTPヘッダインジェクションは過去の(歴史的な)攻撃手法になりかけてはいるものの、まだしぶとく生き残っている、というのが結論です。
【HASHコンサルティング広告】
HASHコンサルティング株式会社は、セキュリティエンジニアを募集しています。
興味のある方は、twitterやfacebookのメッセージ、あるいは問い合わせページからお問い合わせください。
0 件のコメント:
コメントを投稿