php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74129 Incorrect SCRIPT_NAME with apache ProxyPassMatch when spaces are in path.
Submitted: 2017-02-19 17:10 UTC Modified: -
From: christian at groschupp dot org Assigned:
Status: Open Package: FPM related
PHP Version: 7.1.2 OS: CentOS 7.3.1611
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2017-02-19 17:10 UTC] christian at groschupp dot org
Description:
------------
php version: 7.1.2
apache version: 2.4.6

apache configuration:
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/$1


Working apache configuration
<FilesMatch "\.php$">
       SetHandler "proxy:fcgi://localhost:9000"
</FilesMatch>

I need the ProxyPassMatch variant, because i have also a apache 2.2 and php 5.6 setup, where i can't use SetHandler.

Test script:
---------------
# Script to reproduce on CentOS 7

yum install -y epel-release
rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install -y httpd php71-php-fpm

cat << EOF > /var/www/html/index.php
<?php
echo 'Value: ' . \$_SERVER['SCRIPT_NAME'] . '<br>';
echo 'Expected Value: ' . '/index.php'
?>
EOF

scl enable php71 php-fpm

echo "ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/$1" >> /etc/httpd/conf.d/welcome.conf

apachectl -D FOREGROUND

Expected result:
----------------
When requesting "/index.php/1 2 3"

$_SERVER["SCRIPT_NAME"]: "/index.php"

Actual result:
--------------
$_SERVER["SCRIPT_NAME"]: "/index.php/1 2 3"

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-08-08 21:07 UTC] rainer dot jung at kippdata dot de
Adding some partial problem info: I expect the problem to be in the following lines in fpm/fpm_main.c:

1234                                 } else if (apache_was_here && env_script_name) {
1235                                     /* Using mod_proxy_fcgi and ProxyPass, apache cannot set PATH_INFO
1236                                      * As we can extract PATH_INFO from PATH_TRANSLATED
1237                                      * it is probably also in SCRIPT_NAME and need to be removed
1238                                      */
1239                                     int snlen = strlen(env_script_name);
1240                                     if (snlen>slen && !strcmp(env_script_name+snlen-slen, path_info)) {
1241                                         FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
1242                                         env_script_name[snlen-slen] = 0;
1243 SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name);
1244                                     }
1245                                 }
1246                                 env_path_info = FCGI_PUTENV(request, "PATH_INFO", path_info); 

Here SCRIPT_NAME gets compared to PATH_INFO in the strcmp() call. Now when using mod_proxy_fcgi Apache sends SCRIPT_NAME non-percent-encoded as required by the CGI spec. But PATH_INFO is extracted from SCRIPT_FILENAME which is percent-encoded. That means all is fine as long as the PATH_INFO part does not contain anything that gets encoded. As soon as chars which need encoding are contained, the strcmp() fails and SCRIPT_NAME will not get adjusted.

Furthermore, even if SCRIPT_NAME would be encoded, it would still be important, that the percent-encoding of SCRIPT_FILENAME and SCRIPT_NAME use the same character case for the hex digits, eg. not mixing %5B and %5b.

As a workaround I adjusted SCRIPT_NAME in mod_proxy_fcgi to be consistent with SCRIPT_FILENAME even though that's not CGI-spec compliant using the following directive:

ProxyFCGISetEnvIf "reqenv('SCRIPT_FILENAME') =~ m|.*${APP_DIR}(/.*)|" SCRIPT_NAME "$1"

Here APP_DIR is a Unix env var or Define'd var containing the path to the PHP application (could be your DocumentRoot). One can also use the verbatim path there instead of a variable.

the correct fix would probably be to use a percent-decoded path_info in the strcmp() inside fpm_main.c.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Dec 14 20:01:23 2019 UTC