HTTP リクエストに任意の値をセットすることで、Web アプリケーションからの HTTP 通信を傍受したり、中間者攻撃(Man-in-the-Middle)を可能にする脆弱性が見つかっています。
専用サイト
httpoxyという名前が付けられ、専用サイトが立ち上がっています。詳細は、このサイトが詳しいです。
攻撃内容
- アプリケーションからHTTP通信を行う際に、環境変数
HTTP_PROXY
の値を、HTTPプロキシとして見るライブラリがある。 - HTTPリクエストに
Proxy
ヘッダを付けられると、環境変数HTTP_PROXY
にその値がセットされる。(これは、CGIの仕様) - つまり、任意のプロキシを外部から指定できてしまうので、通信内容の傍受や偽装ができてしまう。
対象となる PHP アプリケーション
- HTTP リクエストを受けて動作する PHP アプリケーション
- アプリケーションから、HTTP 通信を行うもの
- 利用している HTTP 通信を行うパッケージなりライブラリが、環境変数
HTTP_PROXY
の値を HTTP プロキシとして扱う場合
対応方法
1 or 2 のいずれかの方法で対応します。
1. httpdサーバ(アプリケーション以前で)Proxy
ヘッダを落とす。
- nginx
- Apache(httpd)
https://www.apache.org/security/asf-httpoxy-response.txt
冒頭の専用サイトでは、Varnish や HAProxy などの対応方法も記載されている。
2. 環境変数HTTP_PROXY
をHTTPプロキシとして利用しないようにする。
- Guzzle
Guzzle がこれに該当していたので、修正版がリリースされている。Guzzle に依存するパッケージでは、6.2.1
以上を使う。
Guzzle の対応コミットは以下。SAPIを確認して、cli
以外では、HTTP_PROXY
を利用しないようになっている。
Drupal が、Guzzle を利用しており、composer.json の依存バージョンを ~6.2
に変更している。Guzzle を利用したアプリケーションならこの対応が参考になる。
- curl
curl は、10年以上前からこの問題を認識しており、大文字のHTTP_PROXY
は見ないようにしていた。
curl explicitly doesn't use uppercase HTTP_PROXY for this reason. We realized this 10+ years ago... :-) https://t.co/H4jRoCPl7q
— Daniel Stenberg (@bagder) July 18, 2016
Linux では、環境変数は case sensitive なので、HTTP_PROXY
と http_proxy
は別ものとなる。
Linux の環境変数って、case sensitive だったよなと思って、念のため確認。 pic.twitter.com/QjzbMe68IG
— Masashi Shinbara (@shin1x1) July 19, 2016
番外. PHP で、HTTP_PROXY
の値を落とす対応はオススメしない
下記のようなPHPコードでの対応は、効果が無い *1 ので、上記 2 つでの対応が望ましい。
$_SERVER['HTTP_PROXY'] = ''; // 環境変数には効果無し putenv('HTTP_PROXY='); // ヘッダから来た値には無効
- Using unset($_SERVER['HTTP_PROXY']) does not affect the value returned from getenv(), so is not an effective mitigation
- Using putenv('HTTP_PROXY=') does not work either (to be precise: it only works if that value is coming from an actual environment variable rather than a header – so, it cannot be used for mitigation) https://httpoxy.org
追記1(2016/07/20)
getenv が Apache の環境変数と真の環境変数の両方をソースにするのに対して、putenv は真の環境変数だけ書き換えるから putenv では効果がないんだわ https://t.co/hXsiEMT7Ea
— ngyuki(えぬじーぶるー) (@ngyuki) July 19, 2016
getenv()
は、SAPI ごとにハンドラを登録することができ、定義されていれば、そちらが優先される仕組みになっています。
github.com
例えば、php-fpm であれば、php-fpm 実行中は、fcgi env から値を取得するようになっています。 github.com
追記2(2016/07/20)
PHP 本体には、すでに修正コミットが入っています。
次のリリース(下記を見る限りは、2016/07/21)に含まれています。
追記3(2016/07/20)
RHEL / CentOS では、すでに httpd パッケージに修正版が出ています。Proxyヘッダの値を、環境変数HTTP_PROXY
の値としてスクリプトに渡さなくなります。
CVE-2016-5387 - Red Hat Customer Portal
CentOS alert CESA-2016:1421 (httpd) [LWN.net] CentOS alert CESA-2016:1421 (httpd) [LWN.net] CentOS alert CESA-2016:1422 (httpd) [LWN.net]
追記4(2016/07/21)
httpoxy 対応版の PHP 7.0.9、5.6.24、5.5.38 がリリースされました。
http://jp2.php.net/downloads.php#v7.0.9
http://jp2.php.net/downloads.php#v5.6.24
http://jp2.php.net/downloads.php#v5.5.38
参考
HTTPoxy - CGI "HTTP_PROXY" variable name clash - Red Hat Customer Portal
*1:$_SERVER['HTTP_PROXY']の値をプロキシとするライブラリがあれば効果はあるが...