如何保护您的服务器免受HTTPoxy漏洞的影响
什么是 HTTPoxy?
2016 年 7 月 18 日,一个名为 HTTPoxy 的 CGI 应用程序漏洞被披露。 攻击者可以通过在请求中传递 HTTP Proxy
标头来利用易受攻击的部署,这将改变应用程序在联系支持服务时使用的 URL。 这可用于泄露凭据、修改对应用程序的响应等。
该漏洞是由 HTTP_PROXY
环境变量(通常用于指定后端代理服务的位置)与 Proxy
HTTP 客户端标头之间的名称冲突引起的。 CGI 规范 要求将客户端提供的标头传递给带有 HTTP_
前缀的环境,用于命名空间。 这种修改与 HTTP_PROXY
等配置变量发生冲突,这些变量也以 HTTP_
开头。 如果 CGI 应用程序或库在没有额外处理的情况下使用此变量,则在尝试连接到代理服务时,它可能最终使用客户端提供的值。
由于此漏洞影响各种类似 CGI 的实现,因此创建了许多安全漏洞标识符:CVE-2016-5386、CVE-2016-5386、CVE -2016-5387、CVE-2016-5388、CVE-2016-1000109和CVE-2016-1000110(当时写作,这些是保留的,但没有填写)。
自 2001 年以来,HTTPoxy 漏洞以某些形式为人所知,但直到最近才被认为是一个普遍存在的问题。 尽管它可能会影响许多部署,但缓解措施非常简单直接。
易受攻击的服务器和应用程序
HTTPoxy 是许多 CGI 实现发现的一般漏洞。 应用程序或服务器可以正确实现 CGI 规范,但仍然容易受到攻击。
要使部署易受攻击,它必须:
- 使用 HTTP_PROXY 环境变量配置代理连接:在应用程序代码本身或使用的任何库中都可以利用。 这是使用环境配置代理服务器的相当标准的方法。
- 使用 HTTP 向后端服务发出请求:由于名称冲突特定于
HTTP_
前缀,因此只有应用程序使用 HTTP 发出的请求才会受到影响。 使用 HTTPS 或任何其他协议的请求不易受到攻击。 - 在 CGI 或类似 CGI 的环境中运行:客户端标头转换为
HTTP_
前缀环境变量的部署很容易受到攻击。 任何符合 CGI 或相关协议(如 FastCGI)的实现都可以做到这一点。
如您所见,部署和应用程序特定因素的组合对于部署易受攻击是必要的。 为了测试您的部署是否受到影响,Luke Rehmann 创建了一个简单的 站点来检查可公开访问的站点是否存在漏洞 。
语言特定信息
特别是 PHP 应用程序应该被审计,因为在 PHP 生态系统中类似 CGI 的部署比在其他语言中更常见。 此外,getenv
方法在流行库中的广泛使用放大了这个问题,因为目前尚不清楚这将返回未经处理的用户输入,而不仅仅是配置变量。 当前受影响的特定库是 Guzzle(4.0.0rc2 及更高版本)、Artax 和 Composer 的 StreamContextBuilder 类。
使用 CGI 部署时发现易受攻击的其他语言是 Python 和 Go。 这些语言更常使用其他不易受攻击的方法部署。 但是,如果使用 CGI,天真地读取 HTTP_PROXY
变量而不修改其行为的库很容易受到攻击。
如何战胜漏洞
幸运的是,HTTPoxy 修复起来相对简单。 该漏洞可以从 Web 服务器层或应用程序或库中解决:
- 应用程序或库在 CGI 环境中时可以忽略
HTTP_PROXY
变量。 - 应用程序或库可以使用不同的环境变量来配置代理连接
- Web 服务器或代理可以取消设置客户端请求中收到的
Proxy
标头
如果您使用的是易受攻击的库,您应该减轻服务器端的威胁,直到有补丁可以解决该问题。 如果您是库或应用程序作者,并且您的项目依赖 HTTP_PROXY
变量来配置代理后端,请考虑使用在类似 CGI 的环境中运行时不会发生冲突的替代变量。 Ruby 和其他一些项目为此使用 CGI_HTTP_PROXY
。
由于 Proxy
标头不是标准的 HTTP 标头,因此几乎在所有情况下都可以安全地忽略它。 这可以在用于将请求定向到应用程序本身的 Web 服务器或负载平衡器中完成。 因为 Proxy
HTTP 标头没有任何标准的合法用途,它几乎总是可以被丢弃。
任何常见的 Web 服务器、负载平衡器或代理都可以取消设置相应的标头。
使用 Apache 删除 HTTP 代理标头
如果您正在运行 Apache HTTP Web 服务器,则 mod_headers
模块可用于取消设置所有请求的标头。
Ubuntu 和 Debian 服务器
要在 Ubuntu 或 Debian 服务器中启用 mod_headers
,请键入:
sudo a2enmod headers
之后,打开全局配置文件:
sudo nano /etc/apache2/apache2.conf
在底部,添加:
/etc/apache2/apache2.conf
. . . RequestHeader unset Proxy early
保存并关闭文件。
检查配置是否有语法错误:
sudo apache2ctl configtest
如果没有报语法错误,重启服务:
sudo service apache2 restart
CentOS 和 Fedora 服务器
对于常规安装,应默认启用 mod_headers
模块。 要取消设置 Proxy
标头,请打开全局配置文件:
sudo nano /etc/httpd/conf/httpd.conf
在底部,添加:
/etc/httpd/conf/httpd.conf
. . . RequestHeader unset Proxy early
完成后保存并关闭文件。
通过键入以下内容检查语法错误:
sudo apachectl configtest
如果没有报告语法错误,请键入以下命令重新启动服务:
sudo service httpd restart
使用 Nginx 删除 HTTP 代理标头
在 Nginx 中,缓解同样是微不足道的。 您可以轻松地为在服务器或上游运行的任何类似 CGI 的环境清理环境。
Ubuntu 和 Debian 服务器
在 Ubuntu 和 Debian 服务器上,设置 FastCGI 代理时,FastCGI 参数通常包含在 fastcgi_params
或 fastcgi.conf
文件中。 您可以在这两个文件中取消设置 HTTP_PROXY
标头:
echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi.conf echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi_params
如果您在配置 FastCGI 代理时没有获取文件之一,请确保在代理位置本身包含同一行:
/etc/nginx/sites-enabled/some_site.conf
. . . location ~ \.php$ { . . . fastcgi_param HTTP_PROXY ""; . . . } }
如果您使用 Nginx 进行常规 HTTP 代理,则还应清除 HTTP Proxy
标头。 HTTP 代理标头在 /etc/nginx/proxy_params
文件中设置。 您可以通过键入以下内容添加规则以取消设置该文件的 Proxy
标头:
echo 'proxy_set_header Proxy "";' | sudo tee -a /etc/nginx/proxy_params
同样,如果您不是从服务器块配置中获取此文件,则必须将其添加到代理位置本身:
/etc/nginx/sites-enabled/some_site.conf
. . . location /application/ { . . . proxy_pass http://127.0.0.1; proxy_set_header Proxy ""; . . . } }
通过键入以下内容检查语法错误:
sudo nginx -t
如果没有报错,重启服务:
sudo service nginx restart
CentOS 和 Fedora 服务器
CentOS 和 Fedora 上的 Nginx 也使用相同的 fastcgi_params
和 fastcgi.conf
文件来配置 FastCGI 代理。 通过键入以下内容取消设置这两个文件中的 HTTP_PROXY
标头:
echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi.conf echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi_params
如果您在配置 FastCGI 代理时没有获取这些文件之一,请确保在代理位置本身包含同一行:
/etc/nginx/nginx.conf
. . . location ~ \.php$ { . . . fastcgi_param HTTP_PROXY ""; . . . } }
如果您使用 Nginx 进行常规 HTTP 代理,则还应清除 HTTP Proxy
标头。 您只需要添加一条规则即可在您正在执行 proxy_pass
的任何位置取消设置 Proxy
标头。 如果您不确定 proxy_pass
的使用位置,您可以轻松搜索配置目录:
grep -r "proxy_pass" /etc/nginx
Output/etc/nginx/nginx.conf.default: # proxy_pass http://127.0.0.1;
任何未注释掉的结果(如上面的示例)都应编辑为包括 proxy_set_header Proxy "";
:
/etc/nginx/nginx.conf
. . . location /application/ { . . . proxy_pass http://127.0.0.1; proxy_set_header Proxy ""; . . . } }
通过键入以下内容检查语法错误:
sudo nginx -t
如果没有报错,重启服务:
sudo service nginx restart
使用 HAProxy 删除 HTTP 代理标头
如果您使用 HAProxy 将流量定向到应用程序服务器,则可以在转发流量之前删除 Proxy
标头。
打开 /etc/haproxy/haproxy.cfg
文件进行编辑:
sudo nano /etc/haproxy/haproxy.cfg
您可以在配置的 frontend
、backend
或 listen
部分中设置 http-request
指令。
/etc/haproxy/haproxy.cfg
frontend www http-request del-header Proxy . . . backend web-backend http-request del-header Proxy . . . listen appname 0.0.0.0:80 http-request del-header Proxy . . .
这些不需要在每个部分中设置,但包含它们不会有什么坏处。 完成后保存并关闭文件。
通过键入以下内容检查语法:
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
如果没有发现问题,请键入以下命令重新启动服务:
sudo service haproxy restart
结论
HTTPoxy 漏洞已经公开了很长时间,可能会影响部署在 Web 上的大量应用程序。 幸运的是,使用任何 Web 服务器本机的标头更改功能很容易修复。