Code Day's Night

ichikawayのブログ

PHPに関するHTTPOXY脆弱性の問題と対応方法

外部から簡単にHTTP_PROXYという環境変数がセットでき、サーバ間通信や外部サイトと連携している場合に影響があるかもしれない脆弱性です。(HTTPoxy. CVE-2016-5385)

PHPの場合はphp-fpm, mod_php, Guzzle4以上やいくつかのライブラリで影響あります。

対応方法は簡単です。


Apache側で対応する場合は、mod_headerを使える状況であれば、confファイルに下記の1行を追加。

RequestHeader unset Proxy


FastCGIの場合は下記の1行を追加。

fastcgi_param HTTP_PROXY "";


Guzzleは6.2.1で対応されたようです。
Release 6.2.1 release · guzzle/guzzle · GitHub
コミットログを見ると、CLIの時のみ、getenv('HTTP_PROXY')を利用するように変更されてますね。
Addressing HTTP_PROXY security vulnerability, CVE-2016-5385 · guzzle/guzzle@9d521b2 · GitHub



問題の原因や、対応方法、再現方法などは下記のサイトが詳しいのでご覧ください。 

httpoxy.org

www.nginx.com

例えば、Guzzle4以上を使っていて外部サイトに裏で通信して何かしようとするときに、HTTP_PROXY環境変数が上書きされてしまうと、そのProxy経由で通信が行われるため、任意のサイトにアクセスさせられたり、中間者攻撃が可能になります。(PHPからの接続先がhttpsで証明書を検証していれば問題ないですが)
この攻撃は簡単にできてしまうため、影響がありそうならすぐに対応しておいたほうが良いです。

 残念ながら、unset($_SERVER['HTTP_PROXY']) putenv('HTTP_PROXY=');としてもgetenv()に影響しないため回避できません。

 

追記1

httpoxyのサイトで示されたように

RequestHeader unset Proxy early

としていましたが、earlyがなくても手元のapacheでは問題なくHTTP_PROXY環境変数がセットされませんでした。earlyは開発者向けのテスト・デバッグ用の設計のようなので、無くしたほうがよいかもしれません。

mod_headers - Apache HTTP サーバ バージョン 2.2

検証方法は、curlコマンドで

curl -H 'Proxy: 127.0.0.1:12345' "http://localhost"

のようにして、Proxyヘッダをセットしてlocalhostのwebサーバに送信。PHP側は、

var_dump($_SERVER['HTTP_PROXY']);
putenv('HTTP_PROXY=');
var_dump(getenv('HTTP_PROXY'));
exit;


のようにして、ヘッダにセットしたProxyが環境変数にセットされているか表示して確認。