Bug 62339 - proxy-fcgi-pathinfo=unescape breaks PATH_INFO and SCRIPT_NAME
Summary: proxy-fcgi-pathinfo=unescape breaks PATH_INFO and SCRIPT_NAME
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy_fcgi (show other bugs)
Version: 2.4.25
Hardware: PC Linux
: P2 blocker (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-04-30 10:13 UTC by Mathieu
Modified: 2018-05-02 16:05 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mathieu 2018-04-30 10:13:41 UTC
To get a PATH_INFO environment variable available to PHP-FPM, the doc http://httpd.apache.org/docs/current/mod/mod_proxy_fcgi.html#env says to add this line in the conf:

  SetEnvIf REQUEST_URI "^/.*\.php/.*$" proxy-fcgi-pathinfo

It does works for ASCII values in PATH_INFO:
  /phpinfo.php/simple-path_info → PATH_INFO = /simple-path_info

However, for values containing spaces or non-ASCII values, it does urlencode them:
  "/phpinfo.php/spaced path_info" → PATH_INFO="/spaced%20path_info"
  "/phpinfo.php/é_accent" → PATH_INFO="/%C3%A9_accent"

So, as I need a PATH_INFO unescaped, and still according to the doc, I valued proxy-fcgi-pathinfo to "unescape":
  SetEnvIf REQUEST_URI "^/.*\.php/.*$" proxy-fcgi-pathinfo=unescape

This does unescape, but it does break strings too:
  "http://example.com/phpinfo.php/spaced path_info"
  → PATH_INFO = hp/spaced path_info
                ^^ Why the last 2 chars of "/phpinfo.php" are here?
  → SCRIPT_NAME = /var/www/html/phpinfo.p
                                        ^^^ It's missing the above "hp".

And it worsen with length of string. It looks like it truncate PATH_INFO by a number of characters related to those it had to unescape :
  - "/phpinfo.php/a 1z" → PATH_INFO="hp/a 1z" ∕ SCRIPT_NAME="/var/www/html/phpinfo.p"
  - "/phpinfo.php/a 1 2z" → PATH_INFO=".php/a 1 2z" / SCRIPT_NAME="/var/www/html/phpinfo"
  - "/phpinfo.php/a 1 2 3z" → PATH_INFO="fo.php/a 1 2 3z" / SCRIPT_NAME="/var/www/html/phpin"
  - "/phpinfo.php/a 1 2 3 4 5z" → PATH_INFO="hpinfo.php/a 1 2 3 4 5z" / SCRIPT_NAME="/var/www/html/p"

It does of course breaks with accented characters too, not only spaces (%20).
Comment 1 Eric Covener 2018-04-30 12:16:28 UTC
For potential relief: A better/later option here is to use the SetHandler style of configuration instead of ProxyPass, which allows the server to do the normal mapping/splitting.
Comment 2 Eric Covener 2018-04-30 12:33:18 UTC
(In reply to Eric Covener from comment #1)
> For potential relief: A better/later option here is to use the SetHandler
> style of configuration instead of ProxyPass, which allows the server to do
> the normal mapping/splitting.

Another option is ProxyFCGISetEnvIf 

Thanks for the detailed report.
Comment 3 Mathieu 2018-04-30 13:30:59 UTC
Thanks Eric for your suggestions.

I may have missed something, but I cannot get the "SetHandler" method to works:
  <FilesMatch "\.php$">
    SetHandler "proxy:unix:/run/php7.0-fpm-www-data.sock|fcgi://localhost/var/www/html"
  </FilesMatch>

Always gives me a "File not found." (both with and without a path_info string), and nothing really more helpful in the logs:
  AH01071: Got error 'Primary script unknown\n'

And "ProxyFCGISetEnvIf" is not yet available in Debian stable (httpd is still 2.4.25, not yet 2.4.26).
Comment 4 Eric Covener 2018-04-30 21:30:22 UTC
(In reply to Mathieu from comment #0)
> To get a PATH_INFO environment variable available to PHP-FPM, the doc
> http://httpd.apache.org/docs/current/mod/mod_proxy_fcgi.html#env says to add
> this line in the conf:
> 
>   SetEnvIf REQUEST_URI "^/.*\.php/.*$" proxy-fcgi-pathinfo
> 
> It does works for ASCII values in PATH_INFO:
>   /phpinfo.php/simple-path_info → PATH_INFO = /simple-path_info
> 
> However, for values containing spaces or non-ASCII values, it does urlencode
> them:
>   "/phpinfo.php/spaced path_info" → PATH_INFO="/spaced%20path_info"
>   "/phpinfo.php/é_accent" → PATH_INFO="/%C3%A9_accent"
> 
> So, as I need a PATH_INFO unescaped, and still according to the doc, I
> valued proxy-fcgi-pathinfo to "unescape":
>   SetEnvIf REQUEST_URI "^/.*\.php/.*$" proxy-fcgi-pathinfo=unescape

OK, this is coming back to me a little bit. I think these settings are intended for non-FPM scenarios, IOW where no external component is trying to second-guess/rewrite these variables.  It is hard to backtrack from the results when FPM may be changing them on the fly. It's likely that FPM's fixups might be confused by one of SCRIPT_NAME and PATH_INFO (and not both) shrinking due to the unescape.

http://people.apache.org/~covener/fakefpm.pl was posted on an older bug and allows you to dump the unconverted vars.

> 
> This does unescape, but it does break strings too:
>   "http://example.com/phpinfo.php/spaced path_info"
>   → PATH_INFO = hp/spaced path_info
>                 ^^ Why the last 2 chars of "/phpinfo.php" are here?
>   → SCRIPT_NAME = /var/www/html/phpinfo.p
>                                         ^^^ It's missing the above "hp".

Are they logged this way in the error_log or just in the script?  I couldn't get this to happen with fpm and a basic config.
Comment 5 Mathieu 2018-05-02 16:05:51 UTC
I'm not sure what to do with "fakefpm.pl"...

> Are they logged this way in the error_log or just in the script?

Nothing in the logs; that's the phpinfo() output.

> I couldn't get this to happen with fpm and a basic config.

So it must be something on my installation. Do you have any idea of where or what to look?

I confirm that if using mod_php there is no such problem, indeed.