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
Apache shows PHP code if .php in URL is not lowercase #973
Comments
Are the source files actually stored with uppercase file extensions? (or are you perhaps bind-mounting files from a case-insensitive filesystem?) Reproducing in a "dev" situation, bind-mounting from a case-insensitive filesystemFirst create directory to play with, and create a "hello world" mkdir -p test && cd test
echo '<?php echo "hello world\n";' > index.php Start a container, bind-mounting the files from my Mac's filesystem (which is case-insensitive); docker run -d --name=test-container -p 4000:80 -v $(pwd):/var/www/html php:apache Lowercase curl 'http://localhost:4000/index.php'
# hello world Any other case indeed shows the source code (:scream:) curl 'http://localhost:4000/index.pHP'
# <?php echo "hello world\n"; This looks bad, but is due to this particular situation; URLs are case-sensitive, so this last example should produce a 404 error page (because there's no file named This is unfortunate, as it won't allow you to (easily) replicate a production environment on Linux (which would be case sensitive). If you're on Docker Desktop for Mac; there is a feature request to allow bind-mounting case-sensitive (I'd have to check what the status of that is (and if it's technically possible)); docker/for-mac#320 Reproducing a "production" situation (case-sensitive filesystem)So to reproduce a "production" situation, let's run a container that doesn't bind-mount from a case-insensitive filesystem: First, remove the test-container docker rm -f test-container Now build an image that contains an docker build -t phptest -<<'EOF'
FROM php:apache
RUN echo '<?php echo "hello world\n";' > index.php
EOF Run the container using that image, and this time, don't bind-mount local files (as the docker run -d --name=test-container -p 4000:80 phptest Trying the same URL's with curl 'http://localhost:4000/index.php'
# hello world But trying with the wrong case, will now correctly produce a 404: curl 'http://localhost:4000/index.pHP'
# <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
# <html><head>
# <title>404 Not Found</title>
# </head><body>
# <h1>Not Found</h1>
# <p>The requested URL was not found on this server.</p>
# < hr>
# <address>Apache/2.4.38 (Debian) Server at localhost Port 4000</address>
#</body></html> So, should this be changed?Both situations are "undesirable" (you wouldn't want your PHP source to be visible), however: Changing the matching to be case-insensitive would be a security risk A website using this image that allows uploading files and that disallows uploading files with a Yes, this would be a pretty bad website (uploaded files should never end up in a location where PHP files are executed), but I've seen my fair share of bad examples unfortunately. Changing this matching would now make them vulnerable. If you are developing a website, and have files with the wrong (non-lowercase) file extension, that's a bug in your project The default configuration should not accommodate for those situations AlternativesA possible alternative would be to add another matching rule that explicitly disallows browsing files with non-lowercase <FilesMatch \.(phP|pHp|pHP|Php|PhP|PHp|PHP)$>
Deny from all
</FilesMatch> So with this <FilesMatch \.(phP|pHp|pHP|Php|PhP|PHp|PHP)$>
Deny from all
</FilesMatch>
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
DirectoryIndex disabled
DirectoryIndex index.php index.html
<Directory /var/www/>
Options -Indexes
AllowOverride All
</Directory> After building a new docker run -d --name=test-container -p 4000:80 -v $(pwd):/var/www/html phptest2 Lowercase curl 'http://localhost:4000/index.php'
# hello world But trying any URL with a non-lowercase curl -I 'http://localhost:4000/index.phP' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
curl -I 'http://localhost:4000/index.pHp' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
curl -I 'http://localhost:4000/index.pHP' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
curl -I 'http://localhost:4000/index.Php' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
curl -I 'http://localhost:4000/index.PhP' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
curl -I 'http://localhost:4000/index.PHp' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
curl -I 'http://localhost:4000/index.PHP' 2>/dev/null | head -n 1
# HTTP/1.1 403 Forbidden
@tianon WDYT? |
I think you've made some really great points. I'm not sure if we should explicitly add anything -- do we have anywhere we can look for what "shared hosting" providers are commonly doing in these cases to give us a hint? The only thing I could possibly add to what you've posted is that the case sensitive version we have now matches what's documented (albeit as an "example") by PHP upstream at https://www.php.net/manual/en/install.unix.apache2.php:
|
Maybe just add @thaJeztah's suggestion to the docs as a "Note"? This would append a RUN printf '<FilesMatch \.(?!php)(?i:php)$> \n\
Require all denied \n\
</FilesMatch>' >> /etc/apache2/apache2.conf |
I had a way to do a redirect to prevent the code from being shown |
If you enter a URL in browser pointing to a PHP file and
.php
at the end is not all lowercase (e.g..phP
,.pHp
,.PHP
, likeexample.com/index.PHP
), Apache shows content of the PHP file.This is because of this config in
/etc/apache2/conf-enabled/docker-php.conf
:To fix it,
FilesMatch
's regexp should be case-insensitive:I can make a pull request but should the change be made in this file?
php/apache-Dockerfile-block-1
Line 45 in a80762e
The text was updated successfully, but these errors were encountered: