Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP-FPM + Apache: special characters in SCRIPT_FILENAME are URL encoded #15246

Open
abgandar opened this issue Aug 5, 2024 · 3 comments
Open
Assignees

Comments

@abgandar
Copy link

abgandar commented Aug 5, 2024

Description

Problem

I use Apache + PHP-FPM to serve PHP files sitting in the server's document root. Some PHP files have spaces and UTF-8 encoded special characters (umlauts, accents) in their file names. Files without spaces or umlauts are served correctly, but files with any of those lead to a 404 with PHP-FPM responding 'Primary script unknown'.

This appears to be due to the way Apache passes the SCRIPT_FILENAME variable: it seems to prefix the physical file name by proxy:fcgi:// and then URL encodes the file name following. So the correctly resolved file name "/docroot/my file.php" gets passed as "proxy:fcgi://my.server/docroot/my%20file.php". PHP-FPM removes the prefix and host name, but then tries to find the file "/docroot/my%20file.php", which doesn't exist.

This seems to me to be related to #12996: the fix to that bug was to URL decode PATH_INFO, but it does not cover the case where the physical script file (SCRIPT_FILENAME) is also URL encoded. So it just URL decodes the bit after the file name.

Symptoms

Using the following PHP-FPM access log format

access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{ORIG_SCRIPT_FILENAME}e"

when requesting the URL

https://my.server/files/test%20me.php

I get logs like this

- -  04/Aug/2024:21:35:48 +0200 "GET /files/test me.php" 404 - /var/htdocs/files/test%20me.php

Note the request (%r) is URL decoded, but the ORIG_SCRIPT_FILENAME is not. The file "/var/htdocs/files/test me.php" exists and is readable by the php-fpm user. Files without the space work fine. I use ORIG_SCRIPT_FILENAME because PHP-FPM unsets SCRIPT_FILENAME when reporting a 404 error (hence the empty %f), but saves the value in ORIG_SCRIPT_FILENAME.

Setup

I'm using PHP 8.3.10 with Apache/2.4.62 (FreeBSD) OpenSSL/3.2.2 on FreeBSD 14.1-STABLE (both built from ports).

Relevant Apache config:

    <FilesMatch "\.php$">
        SetHandler "proxy:unix:/var/run/php-fpm.sock|fcgi://php-fpm"
    </FilesMatch>
 
    <Proxy "fcgi://php-fpm" enablereuse=off max=18>
    </Proxy>

    # PHP Apache FCGI hack to pass HTTP AUTH info
    ProxyFCGISetEnvIf "%{HTTP:Authorization} =~ /(.+)/" HTTP_AUTHORIZATION "$1"
    ProxyFCGISetEnvIf "%{REMOTE_USER} =~ /(.+)/" PHP_AUTH_USER "$1"

My PHP-FPM setup is stock with UNIX socket at /var/run/php-fpm.sock and access logging as per above.

I have had this setup unchanged for several years and PHP and Apache versions. I'm pretty sure this worked about half a year ago, but can't say when precisely this broke (and if it was a change on the Apache or PHP side).

Workaround

As a workaround, I can make everything run just fine by forcing Apache to unescape the SCRIPT_FILENAME variable before passing it to PHP-FPM:

    ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "%{unescape:%{SCRIPT_FILENAME}}"

I don't know what that does to PATH_INFO stuff as I don't use that.

Solution(?)

Since fpm_main.c already does a lot of gymnastics to fix Apache's botched inputs, it may be better to unescape the SCRIPT_FILENAME when removing the "proxy:fcgi://" prefix in fpm_main.c.

Unfortunately, I don't fully understand all the logic there, and am not familiar enough with PHP sources to confidently propose a fix.

PHP Version

PHP 8.3.10

Operating System

FreeBSD 14.1-STABLE

@devnexen
Copy link
Member

devnexen commented Aug 5, 2024

sorry @cmb69 was unaware you were editing labels too :)

@bukka
Copy link
Member

bukka commented Aug 5, 2024

I have been just reading about this on Apache devel mailing list and it is actually Apache httpd regression in 2.4.61 - https://bz.apache.org/bugzilla/show_bug.cgi?id=69203 .

I'm just checking if there's anything we can do on PHP-FPM side, test the recent patches for this issue and potentially agree on some better solution for the future. In addition I will be setting up some integration tests to prevent this getting released in the future.

@fvlasie
Copy link

fvlasie commented Aug 30, 2024

I have two almost identical systems. One has the problem, one does not. I fixed the issue using abgandar's workaround for which I am very grateful! (Later note: i realised that one server is ARM and the other is x86.)

The only difference in the Apache versions is the build date.

System 1 ARM (no issue)

Rocky Linux 9.4

Server version: Apache/2.4.57 (Rocky Linux)
Server built:   Feb  7 2024 00:00:00

PHP 8.0.30 (fpm-fcgi) (built: Aug  3 2023 17:13:08)
Zend Engine v4.0.30, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.30, Copyright (c), by Zend Technologies

System 2 x86 (has issue)

Rocky Linux 9.4

Server version: Apache/2.4.57 (Rocky Linux)
Server built:   Aug  5 2024 00:00:00

PHP 8.2.13 (fpm-fcgi) (built: Nov 21 2023 09:55:59)
Zend Engine v4.2.13, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.13, Copyright (c), by Zend Technologies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants