- URL: https://www.laruence.com/en/2010/05/20/1495.html
- Please include attribution when republishing.
The usual Nginx + PHP cgi setup sets SCRIPT_FILENAME in the config file with a regex match (The PATH_INFO Problem with Nginx (PHP/fastcgi)). Today Xiaodun found a security hole in this approach.
Say you have http://www.laruence.com/fake.jpg. Craft the following URL and you can see the binary contents of fake.jpg:
http://www.laruence.com/fake.jpg/foo.php
Why does that happen?
Take this nginx conf:
location ~ .php($|/) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
set $script $uri;
set $path_info "";
if ($uri ~ "^(.+.php)(/.*)") {
set $script $1;
set $path_info $2;
}
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$script;
fastcgi_param SCRIPT_NAME $script;
fastcgi_param PATH_INFO $path_info;
}
After the regex match, SCRIPT_NAME is set to "fake.jpg/foo.php", which is then built into SCRIPT_FILENAME and handed to PHP CGI. But why does PHP accept that kind of parameter and go on to parse a.jpg?
That brings us to the fix_pathinfo parameter in PHP's cgi SAPI:
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's ; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok ; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting ; this to 1 will cause PHP CGI to fix it's paths to conform to the spec. A setting ; of zero causes PHP to behave as before. Default is 1. You should fix your scripts ; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. cgi.fix_pathinfo=1
If this option is enabled, the following logic in PHP kicks in:
/* * if the file doesn't exist, try to extract PATH_INFO out * of it by stat'ing back through the '/' * this fixes url's like /info.php/test */ if (script_path_translated && (script_path_translated_len = strlen(script_path_translated)) > 0 && (script_path_translated[script_path_translated_len-1] == '/' || ....//omitted below.
At this point PHP believes SCRIPT_FILENAME is fake.jpg and foo.php is PATH_INFO, so it happily interprets fake.jpg as a PHP file... So...
In Xiaodun's words, the harm this hides is enormous.
For a forum, all it takes is uploading an image (which is really a malicious PHP script) and then crafting a request like the one above...
So if you run this server combination, please check. If you are exposed, turn off fix_pathinfo (it is on by default).
For the full vulnerability details, head over to Xiaodun's BLOG: 80Sec
One more thing: I don't think this has much to do with Nginx, and it is not an Nginx vulnerability. It is a configuration problem, yet everywhere people are calling it an Nginx Bug. Not right, not right.
Be First to Comment