On July 18th, 2016, a CGI application vulnerability, referred to as HTTPoxy, was disclosed. An attacker can exploit vulnerable deployments by passing an HTTP Proxy
header with their request, which will alter the URL used by the application when contacting backing services. This can be used to leak credentials, modify responses to the application, etc.
The vulnerability is caused by a name collision between the HTTP_PROXY
environmental variable, frequently used to specify the location of a backend proxy service, and the Proxy
HTTP client header. The CGI specification calls for client-provided headers to be passed to the environment with a HTTP_
prefix for namespacing. This mangling clashes with configuration variables like HTTP_PROXY
, which also start with HTTP_
. If a CGI application or a library uses this variable without additional processing, it could end up using the value provided by the client when attempting connections to the proxy service.
As this vulnerability impacts a variety of CGI-like implementations, a number of security vulnerability identifiers have been created: CVE-2016-5386, CVE-2016-5386, CVE-2016-5387, CVE-2016-5388, CVE-2016-1000109, and CVE-2016-1000110 (At the time of this writing, these are reserved, but not filled out).
The HTTPoxy vulnerability has been known in some forms since 2001, but never recognized as a widespread issue until recently. Although it may affect many deployments, mitigation is quite simple and straight forward.
HTTPoxy is a general vulnerability found by many CGI implementations. An application or server can correctly implement the CGI specification and still be vulnerable.
For a deployment to be vulnerable, it must:
HTTP_PROXY
environmental variable to configure proxy connections: Either in the application code itself or any libraries that are used leverages. This is a fairly standard method of configuring proxy servers using the environment.HTTP_
prefix, only requests made by the application using HTTP will be affected. Requests using HTTPS or any other protocols are not vulnerable.HTTP_
prefixed environmental variables are vulnerable. Any compliant implementation of CGI or related protocols like FastCGI will do this.As you can see, a combination of deployment- and application-specific factors are necessary for a deployment to be vulnerable. To test whether your deployment is affected, Luke Rehmann has created a simple site to check publicly accessible sites for vulnerability.
PHP applications in particular should be audited, since CGI-like deployments are much more common in the PHP ecosystem than in other languages. Furthermore, the widespread usage of the getenv
method in popular libraries amplifies this issue, as it is not immediately clear that this will return unsanitized user input, not just configuration variables. Specific libraries that are currently affected are Guzzle (version 4.0.0rc2 and greater), Artax, and Composer’s StreamContextBuilder class.
Other languages that were found to be vulnerable when deployed using CGI were Python and Go. These languages are more commonly deployed using other, non-vulnerable methods. However, if CGI is used, libraries that naively read the HTTP_PROXY
variable without modifying their behavior are vulnerable.
Fortunately, HTTPoxy is relatively simple to fix. The vulnerability can be addressed from the web server layer or the application or library:
HTTP_PROXY
variable when they are in a CGI environment.Proxy
header received in client requestsIf you are using a vulnerable library, you should mitigate the threat on the server end until patches are available to address the issue. If you are a library or application author and your project relies on the HTTP_PROXY
variable to configure a proxy backend, consider using an alternative variable that will not clash when running in a CGI-like environment. Ruby and some other projects use CGI_HTTP_PROXY
for this purpose.
Since the Proxy
header is not a standard HTTP header, it can be safely ignored in almost all cases. This can be done in the web server or load balancer used to direct requests to the application itself. Because the Proxy
HTTP header does not have any standard legitimate purpose, it can almost always be dropped.
Any common web server, load balancer, or proxy can unset the appropriate headers.
If you are running the Apache HTTP web server, the mod_headers
module can be used to unset the header for all requests.
To enable mod_headers
in Ubuntu or Debian servers, type:
- sudo a2enmod headers
Afterwards, open the global configuration file:
- sudo nano /etc/apache2/apache2.conf
Towards the bottom, add:
. . .
RequestHeader unset Proxy early
Save and close the file.
Check the configuration for syntax errors:
- sudo apache2ctl configtest
Restart the service if no syntax errors are reported:
- sudo service apache2 restart
The mod_headers
module should be enabled by default for conventional installations. To unset the Proxy
header, open the global configuration file:
- sudo nano /etc/httpd/conf/httpd.conf
Towards the bottom, add:
. . .
RequestHeader unset Proxy early
Save and close the file when you are finished.
Check for syntax errors by typing:
- sudo apachectl configtest
If no syntax errors are reported, restart the service by typing:
- sudo service httpd restart
In Nginx, mitigation is similarly trivial. You can easily sanitize the environment for any CGI-like environment running on the server or upstream.
On Ubuntu and Debian servers, FastCGI parameters are typically included from either the fastcgi_params
or fastcgi.conf
files when setting up a FastCGI proxy. You can unset the HTTP_PROXY
header in both of these files:
- echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi.conf
- echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi_params
If you are not sourcing one of files when configuring your FastCGI proxies, be sure to include this same line in the proxy location itself:
. . .
location ~ \.php$ {
. . .
fastcgi_param HTTP_PROXY "";
. . .
}
}
If you are using Nginx for conventional HTTP proxying, you should clear the HTTP Proxy
header as well. HTTP proxying headers are set in the /etc/nginx/proxy_params
file. You can add the rule to unset the Proxy
header to that file by typing:
- echo 'proxy_set_header Proxy "";' | sudo tee -a /etc/nginx/proxy_params
Again, if you are not sourcing this file from within your server block configuration, you’ll have to add it in the proxy location itself:
. . .
location /application/ {
. . .
proxy_pass http://127.0.0.1;
proxy_set_header Proxy "";
. . .
}
}
Check for syntax errors by typing:
- sudo nginx -t
If no errors are reported, restart the service:
- sudo service nginx restart
Nginx on CentOS and Fedora also uses the same fastcgi_params
and fastcgi.conf
files to configure FastCGI proxying. Unset the HTTP_PROXY
header in both of these files by typing:
- echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi.conf
- echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi_params
If you are not sourcing one of these files when configuring your FastCGI proxies, be sure to include this same line in the proxy location itself:
. . .
location ~ \.php$ {
. . .
fastcgi_param HTTP_PROXY "";
. . .
}
}
If you are using Nginx for conventional HTTP proxying, you should clear the HTTP Proxy
header as well. You just need to add a rule to unset the Proxy
header in any location where you are executing a proxy_pass
. If you are unsure where proxy_pass
is being used, you can easily search your configuration directory:
- grep -r "proxy_pass" /etc/nginx
Output/etc/nginx/nginx.conf.default: # proxy_pass http://127.0.0.1;
Any results that are not commented out (like the example above) should be edited to include proxy_set_header Proxy "";
:
. . .
location /application/ {
. . .
proxy_pass http://127.0.0.1;
proxy_set_header Proxy "";
. . .
}
}
Check for syntax errors by typing:
- sudo nginx -t
If no errors are reported, restart the service:
- sudo service nginx restart
If you are using HAProxy to direct traffic to your application servers, you can drop the Proxy
header before forwarding the traffic.
Open up the /etc/haproxy/haproxy.cfg
file for editing:
- sudo nano /etc/haproxy/haproxy.cfg
You can set the http-request
directive in the frontend
, backend
, or listen
sections of your configuration.
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
. . .
These do not need to be set in each of the sections, but it won’t hurt to include them. Save and close the file when you are finished.
Check the syntax by typing:
- sudo haproxy -c -f /etc/haproxy/haproxy.cfg
If no problems are found, restart the service by typing:
- sudo service haproxy restart
The HTTPoxy vulnerability has been out in the open for quite a long time and may affect a large set of applications deployed on the web. Luckily, it is easy to fix using the header-altering capabilities native to any web server.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
@jellingwood Are this corret?
For servers managed by ServerPilot, the HTTPoxy fix is already applied. No further action is needed.
https://serverpilot.io/blog/2016/07/19/httpoxy-vulnerability.html
This comment has been deleted