nginx 0day exploit for nginx + fastcgi PHP

Weibin Yao nbubingo at gmail.com
Mon May 24 12:13:41 MSD 2010


Jérôme Loyet at 2010-5-24 14:56 wrote:
> 2010/5/24 Weibin Yao <nbubingo at gmail.com>:
>   
>> Jérôme Loyet at 2010-5-22 3:45 wrote:
>>     
>>> 2010/5/21 Igor Sysoev <igor at sysoev.ru>:
>>>
>>>       
>>>> On Fri, May 21, 2010 at 02:26:31PM -0400, Ian Evans wrote:
>>>>
>>>>
>>>>         
>>>>> Is this situation only pertaining to sites that allow uploads from
>>>>> forms?
>>>>>
>>>>> Going way back to this thread
>>>>> (http://www.ruby-forum.com/topic/145358#645652) in '08, I needed
>>>>> cgi.fix-pathinfo=1 to fix problems with paths and specific extensionless
>>>>> files I needed run as php.
>>>>>
>>>>> Changing cgi.fix-pathinfo=1 to 0 broke a lot of stuff.
>>>>>
>>>>>           
>>>> Could you show again how URIs should be mapped to SCRIPT_FILENAME
>>>> and PATH_INFO ? Modern nginx versions support named captures in regex.
>>>>
>>>>
>>>>         
>>> hi igor,
>>>
>>> this a very interesting situation :) And i could be a real security
>>> hole on some configuration.
>>>
>>> Let say you have the default configuration (except for the
>>> SCRIPT_FILENAME which has been adapted for my local conf where the
>>> fastcgi server is running on local and uses the same document root as
>>> nginx)
>>>
>>> location ~ \.php$ {
>>>    root           html;
>>>    fastcgi_pass   127.0.0.1:9000;
>>>    fastcgi_index  index.php;
>>>    fastcgi_param  SCRIPT_FILENAME  $request_filename;
>>>    include        fastcgi_params;
>>> }
>>>
>>>
>>> Let say the request is
>>> http://mydomain/foo/test.php/virtual/path/to/somewhere.php
>>>
>>> the fastcgi request sends the following fastcgi parameters
>>> SCRIPT_FILENAME is set to
>>> /nginx/prefix/html/foo/test.php/virtual/path/to/somewhere.php
>>> PATH_INFO is not set
>>>
>>> with fix_pathinfo=1
>>> SCRIPT_FILENAME is transformed to /nginx/prefix/html/foo/test.php
>>> PATH_INFO is set to /virtual/path/to/somewhere.php
>>> in this case, PHP could parse and execute an unwanted file and a
>>> security hole can exists.
>>>
>>> with fix_pathinfo=1
>>> SCRIPT_FILENAME is not changed and still
>>> /nginx/prefix/html/foo/test.php/virtual/path/to/somewhere.php
>>> PATH_INFO is not changed and remains unset
>>> in this case, PHP tries to execute the file which really corresponds
>>> to the request which will certenely not exist.
>>>
>>> In both case, if the (updated) SCRIPT_FILENAME corresponds to an
>>> existing file on the filesystem, it's interpreted by PHP.
>>>
>>> Is it a PHP bug ? I don't really know. fix_pathinfo is a feature which
>>> could be usefull on some case (otherwise why would have it been done
>>> ?).
>>> Is it a nginx bug ? I don't think so. It's how nginx works. The guy
>>> who makes the conf should understand what he's doing. But .. see my
>>> following question
>>>
>>> Why nginx forwards the request to the fastcgi server if the
>>> SCRIPT_FILENAME does not exists ?
>>> 1- if the fastcgi server is not local, the local machine does not have
>>> the script file on its filesystem --> nginx can't check if the file
>>> exists. It would say NO instead of YES.
>>> 2- if the fastcgi server is local but running with a user which
>>> doesn't have rights to search for the script filename --> nginx can't
>>> check if the file exists. It would say NO instead of YES
>>> 3- if the fastcgi server is local and have access to the file -->
>>> nginx can return 404 without sending the request to the fastcgi
>>> server. This is usefull in this security case, but it's also a
>>> performance enhancement because the fastcgi server won't deal with non
>>> existing files and 404 will be returned quicker and less resources
>>> will be used
>>>
>>> Igor, maybe the default conf file is not that good about PHP through
>>> fastcgi.
>>> here is an idea:
>>> --- nginx.conf.orig     2010-05-21 21:31:45.000000000 +0200
>>> +++ nginx.conf  2010-05-21 21:36:00.000000000 +0200
>>> @@ -64,9 +64,12 @@
>>>         #
>>>         #location ~ \.php$ {
>>>         #    root           html;
>>> +        #    if (!-e $request_filename) {
>>> +        #        return 404;
>>> +        #    }
>>>         #    fastcgi_pass   127.0.0.1:9000;
>>>         #    fastcgi_index  index.php;
>>> -        #    fastcgi_param  SCRIPT_FILENAME
>>>  /scripts$fastcgi_script_name;
>>> +        #    fastcgi_param  SCRIPT_FILENAME  $request_filename;
>>>         #    include        fastcgi_params;
>>>         #}
>>>
>>>
>>> or maybe just add a BIG warning to disable fix.path_info and use
>>> fastcgi_split_path_info to deals with those kind of URL
>>>
>>>       
>> I think we should use the directive of fastcgi_split_path_info and add
>> PATH_INFO by nginx itself.
>>     
>>> On my side, I'll check if the fix_pathinfo is really usefull on
>>> php-fpm. If not, I'll try to remove it.
>>>
>>>       
>> The php developer said this feature is very useful in the mod_rewrite with
>> the PATH_INFO parameter.
>>     
>
> do you have any links to discution about this ? or concrete examples ?
>
> thx
>   
Sorry,  I just asked a PHP developer(Dmitry Stogov, dmitry at zend.com) by 
email last firday and I know nothing about php.

I asked:"Is there any other side effect if I turn off the 
cgi.fix_pathinfo, except the feature with mod_rewrite?"

he said:"I think no, but I can to sure for 100%. I looked into that code few years ago."

>   
>>> hope this help!
>>>
>>> ++ Jerome
>>>
>>> _______________________________________________
>>> nginx mailing list
>>> nginx at nginx.org
>>> http://nginx.org/mailman/listinfo/nginx
>>>
>>>
>>>       
>> --
>> Weibin Yao
>>
>>
>> _______________________________________________
>> nginx mailing list
>> nginx at nginx.org
>> http://nginx.org/mailman/listinfo/nginx
>>
>>     
>
> _______________________________________________
> nginx mailing list
> nginx at nginx.org
> http://nginx.org/mailman/listinfo/nginx
>
>   


-- 
Weibin Yao




More information about the nginx mailing list