While I was thinking about certain ways of summarizing CSRF prevention for OWASP PHP Security Cheat Sheet – mixing taint tracking with different request criteria – I found a certain type of attack against certain high-level web applications and frameworks, which I named it HTTP Host Alteration Attack.
Many web appl1ications rely on the HTTP host (accessible via $_SERVER[‘HTTP_HOST’] in PHP) to determine their running environment, e.g development or deployment. For example, if HTTP_HOST is localhost, 127.0.0.1, or 192.168.*.*, the application is presumably running in development mode, so it would dump error details, SQL queries, profiling details and more importantly, stack traces.
When the application is running on a deployment server, it logs errors instead of dumping them, and reduces critical details on the screen. Also credentials for connecting to the database and other 3rd party tools are different on development and deployment servers.
The code snippet below, taken from earlier versions of the almighty jFramework, is used to determine the running state of the application:
if (jURL::HTTPHost()==”localhost”)
reg(“app/state”,”develop”);
elseif (strpos(jURL::HTTPHost(),”jframework.info”)!==false) #replace this with your site
reg(“app/state”,”deploy”);
elseif (php_sapi_name()==”cli”)
reg(“app/state”,”develop”);
else
trigger_error(“No running state determined.”);
Then the rest of application behaviors are determined by this state. Now what the developer (embarrassingly myself) had forgotten there, was that HTTP Host is provided with the HTTP Request, and though it is part of the standard HTTP protocol and should ALWAYS be provided and valid, can easily be forged by an attacker.
I became aware of this issue while using my Mozilla Add-on, IRUnfilter, to get around Iran’s Internet restrictions. IRUnfilter removes the Host header from HTTP Request – which is used by government to determine if a site is allowed or not – and sends the request to a web proxy outside Iran, which effectively replaces the host header with the valid value. Now if you skip the proxy and visit a jFramework powered website using it, the “No running state determined.” error would pop-up.
An attacker could simply replace the Host header instead of removing it, with something fabulous such as “localhost”, to get “Development” access to the deployed application. I was about to advertise jFramework’s old method of determining the state in OWASP’s wiki, but fortunately I was a little busy and started to realize this issue before publishing it to the world!