A short time ago an old security issue was revealed to still be present in many modern application servers. The issue is now known as HTTPoxy, and no fewer than 6 CVE's were issued to document the vulnerabilities in various web application platforms. Phusion Passenger is not vulnerable to HTTPoxy and Ruby applications in general are not either. In this article we will give a short description of the problem, explain why applications hosted by Passenger are not vulnerable, why Ruby applications in general are not vulnerable and give some more background information on the topic.
What is HTTPoxy?
HTTPoxy is the name for a vulnerability that arises in application servers that communicate HTTP headers to the application through environment variables as defined in the Common Gateway Interface (CGI) specification. The header that causes the issue is PROXY
, which is passed to the application prefixed with HTTP_
.
The vulnerability emerges when the resulting HTTP_PROXY
environment variable is subsequently interpreted by the application server’s HTTP libraries as a proxy to route any outgoing HTTP connections through. An example of this could be a Python Django application that requests an authentication token from an uncertified internal authentication service using the requests
library:
- The attacker sends an authentication request to the Django application, having set the
PROXY
HTTP header to an ip address that they control. - The CGI gateway sees the HTTP header, adds the prefix and sets it as the environment variable
HTTP_PROXY
. - The Django application uses the
requests
library to fetch an authentication token. The library notices theHTTP_PROXY
environment variable and routes the authentication token request through the address set as its value. - The attackers proxy server receives the request and responds with an access granting authentication token, gaining full access to the application.
This example is just one of many scenarios that could end with an attacker gaining various degrees of access or control over your systems.
Why are Passenger and Ruby applications in general not vulnerable?
The fundamental reason for Passenger not being vulnerable is that application server protocol specifications such as Rack and WSGI have allowed Passenger to be more tightly integrated with the application platform and eschew communication through environment variables as CGI specifies. Phusion Passenger not only spins up the worker processes for the application but also sets the HTTP headers in the application directly as local variables. This same integration enables many of the Passenger's enterprise features such as the ability to attach a debugger to a running Ruby application.
Where Python applications could be vulnerable if they were hosted using CGI, pure Ruby applications would actually be safe. This is because during the implementation of the HTTP_PROXY
support in Ruby's net/http
Akira Tanaka noticed this exact vulnerability and the team implemented a mitigation.
When is my application vulnerable?
Your application is vulnerable if it is hosted by an application server that uses CGI to communicate with the application and that uses an http request library that honours the HTTP_PROXY
environment variable for proxying outgoing requests such as Python's request, PHP's Guzzle and Artax, and Go's net/http
. A more complete list is maintained here.
What should I do when my application is vulnerable?
If you use an application server like Passenger, your application is automatically protected against HTTPoxy. You can also use a protective reverse proxy like Cloudflare.
Alternatively, you can filter out the HTTP PROXY
header at the web server level (not the application level). For example, on Nginx you might use this snippet in your server block:
fastcgi_param HTTP_PROXY "";
Conclusion
HTTPoxy is a serious vulnerability in applications hosted by CGI servers and it is important to identify such applications and apply measures to make sure they are not vulnerable. Phusion Passenger users do not have to worry about HTTPoxy because Passenger does not overwrite environment variables with HTTP headers. We have also described some other ways to deal with the vulnerability.