如何保护您的服务器免受HTTPoxy漏洞的影响

来自菜鸟教程
跳转至:导航、​搜索

什么是 HTTPoxy?

2016 年 7 月 18 日,一个名为 HTTPoxy 的 CGI 应用程序漏洞被披露。 攻击者可以通过在请求中传递 HTTP Proxy 标头来利用易受攻击的部署,这将改变应用程序在联系支持服务时使用的 URL。 这可用于泄露凭据、修改对应用程序的响应等。

该漏洞是由 HTTP_PROXY 环境变量(通常用于指定后端代理服务的位置)与 Proxy HTTP 客户端标头之间的名称冲突引起的。 CGI 规范 要求将客户端提供的标头传递给带有 HTTP_ 前缀的环境,用于命名空间。 这种修改与 HTTP_PROXY 等配置变量发生冲突,这些变量也以 HTTP_ 开头。 如果 CGI 应用程序或库在没有额外处理的情况下使用此变量,则在尝试连接到代理服务时,它可能最终使用客户端提供的值。

由于此漏洞影响各种类似 CGI 的实现,因此创建了许多安全漏洞标识符:CVE-2016-5386CVE-2016-5386CVE -2016-5387CVE-2016-5388CVE-2016-1000109CVE-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_paramsfastcgi.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_paramsfastcgi.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

您可以在配置的 frontendbackendlisten 部分中设置 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 服务器本机的标头更改功能很容易修复。