PHP-FPM security

18 posts / 0 new
Last post
#1 Fri, 10/11/2019 - 10:25
cuscus

PHP-FPM security

Hi folks,

as PHP-FPM runs as virtual server user, PHP scripts will have read access to all files under users home directory. User might have SSH keys and/or other confidental details there.

Is there any proper way allow PHP to read only files that are required for the website/app to run? Using open_basedir shouldn't be acceptable as it disables realpath cache.

Sat, 10/12/2019 - 14:50
Dibs

I believe you can have PHP-FPM start an individual pool (per user for a particular website). In which case I would expect each pool to be restricted to a website & by extension only files in that users\websites home directory. So you could have multiple pools running - one for each website.

Sat, 10/12/2019 - 15:27
anahata
anahata's picture

The user who deploys PHP code on their web site is entitled to access their .ssh directory and other confidential information in their own home directory. Surely it's up to them to make sure that information is not exposed to visitors to their web site, by not writing insecure PHP code.

File permissions and ownership can be set so that one user cannot access another user's home directory. I set all mine owned by user:user (the Debian standard) and permissions to 750 to achieve that.

But I also use open_basedir anyway, to protect system directories for access by PHP code. I wasn't aware of the performance implications (which I've just been reading about now) and I see that it's not very reliable either, so maybe there's a better solution like chroot jails per user.

Anahata www.treewind.co.uk West Yorkshire, UK

Sat, 10/12/2019 - 15:30
anahata
anahata's picture

The user who deploys PHP code on their web site is entitled to access their .ssh directory and other confidential information in their own home directory. Surely it's up to them to make sure that information is not exposed to visitors to their web site, by not writing insecure PHP code.

File permissions and ownership can be set so that one user cannot access another user's home directory. I set all mine owned by user:user (the Debian standard) and permissions to 750 to achieve that.

But I also use open_basedir anyway, to protect system directories for access by PHP code. I wasn't aware of the performance implications (which I've just been reading about now) and I see that it's not very reliable either, so maybe there's a better solution like chroot jails per user.

Anahata www.treewind.co.uk West Yorkshire, UK

Sat, 10/12/2019 - 15:53 (Reply to #4)
Dibs

If you use separate PHP-FPM pools per user\domain - can't you specify something like

php_admin_value[open_basedir] = /home/nginx/domains/domain1.com/public

for each pool?

Sat, 10/12/2019 - 17:50
anahata
anahata's picture

Dibs - yes, you can use open_basedir like that and I have have done on my system.
The original poster didn't want to use open_basedir for performance reasons.

Anahata www.treewind.co.uk West Yorkshire, UK

Sat, 10/12/2019 - 18:10
anahata
anahata's picture

Here's something much better than open_basedir: Administration Options -> edit owner limits ->other restrictions
There is a switch for "Chroot jail domain Unix user"
This will make ssh and PHP-FPM or FCGID run in a chroot jail in the users home directory.
It still won't stop PHP scripts from accessing their own .ssh, Maildir or subdomains, but it will isolate users form each other and system files. I might try it on a harmless domain.

Anahata www.treewind.co.uk West Yorkshire, UK

Sat, 10/12/2019 - 18:55
cuscus

With PHP-FPM Virtualmin already creates separate pools for each user, so users won't have any access to each others files. But as pool is owned by user, php have full access to users own files within home directory and these files might include confidental information like ssh keys, users emails, bash history etc.

As mentioned, open_basedir is an option, but it affects permormance quite a bit and also it often brings other issues, for example with is_readable. Quick Google search reveals lots of WordPress plugins having issues with this as well.

Chroot/jail definitely brings more separation between user accounts, but it won't fix this php permission issue. All the same users files will be within the jail anyway and php can still access them.

Sun, 10/13/2019 - 05:38
anahata
anahata's picture
php have access to users own files

PHP scripts created and uploaded by that user have access... so I think your only option is to make sure you upload safe PHP code that can't be made to access those files. Filter input and output, maybe use the PHP disable_functions directive in the FPM config file to outlaw dangerous functions.

Anahata www.treewind.co.uk West Yorkshire, UK

Sun, 10/13/2019 - 07:34
cuscus

Also php scripts updated and uploaded by your scripts will have full access to your files. This might become an issue with CMS's like WordPress, as plugins get updated.

Maybe running php as a completely separate user could be a solution, let's say user1-php and your files are owned by user1 which would be added to user1-php group. That way php could write only to group writable directories/files and there wouldn't be any performance issues at all.

Sun, 10/13/2019 - 13:51 (Reply to #10)
Dibs

cuscus - when you say "Maybe running php as a completely separate user could be a solution, let's say user1-php and your files are owned by user1 which would be added to user1-php group. That way php could write only to group writable directories/files and there wouldn't be any performance issues at all."

For my benefit, you aren't referring to running individual pools per user/domain/group? Assuming not, in the case of 2 users (user1 & user2) would you then have effectively 2 complete PHP installs running - one as user1 & another as user2?

Sun, 10/13/2019 - 14:05 (Reply to #11)
cuscus

In this suggestion there would be individual fpm pools so that all accounts would be separated even more than they are now. I'll try to explain myself a bit better :)

So for each user (virtual host) there would be individual php-fpm user.

User1:

  • files are owned by user1:user1
  • php-fpm is running as user1-fpm:user1-fpm
  • user1 is added to user1-fpm group, which allows php to write to write group writable directories (775)

With this setup php would have access only to files which are group readable. This would disable complete the ability for php to read ssh keys for example.

Sun, 10/13/2019 - 14:16 (Reply to #12)
Dibs

So you'd have individual .conf files for each PHP-FPM pool\user like

; pool name
[sitea]
...
; Unix user/group of processes
; will be used.
user = sitea
group = sitea
...
; Socket to which the Apache will connect
listen = /run/php/php7.0-fpm-sitea.sock

where usera (user) and usera (group) are both unix users\groups?

But user\group sitea would have permissions to only diretories\files that don't have sensitive stuff? So for each virtual server (domain) you might have the standard user which has full permissions and then create another user\group that has less permissions purely for PHP-FPM?

Sorry if I seem a little slow on the uptake. ;)

Sun, 10/13/2019 - 14:25 (Reply to #13)
cuscus

Yes, there would be one user who owns all the files within his/hers home directory and then another user purely for php-fpm. This php user wouldn't be able to login, it's just for running site owners php pool.

In your pool example config, if site owner is "sitea", then pool user and group should be something else, like "sitea-fpm". The name doesn't really matter as long as it's different than site owners username.

Does this make any sense? I'm basically just playing with the idea so far.

Sun, 10/13/2019 - 14:31 (Reply to #14)
Dibs

cuscus - I understand perfectly. 2 "levels" of accounts - the site owner with full rights, maybe ftp, ssh, etc. and can read\write all files\directories and then a 2nd level of user\group just for PHP-FPM not having access to sensitive stuff.

Thanks for clarifying. I recently switched to PHP-FPM and the VPS is running a lot better. But all the pools run as www-data at the moment. So I'm tempted to go down this route too. Only a few virtual servers - so no real headache to try it out. I have 2 WP sites and a simple one. I think I might do the simple one 1st and then try it out on the WP sites.

Sun, 10/13/2019 - 14:38 (Reply to #15)
cuscus

In your current setup when all pools are running as www-data, php have access to group readable files across your sites (user accounts), unless you're using jailkit or other mechanism to chroot them.

Sun, 10/13/2019 - 17:50 (Reply to #16)
Dibs

You are right.

That's the reason to looking at doing something better. Thankfully I manage all 3 sites so I am not too worried about it. But moving to a better way is always good.

I think I might initially split the pools currently run by www-data to be individual pools per virtual server\domain (using the domain owner\user). Then move to ones that use a less privileged user for each domain\server. Like a 2 step approach.

Sun, 10/13/2019 - 13:15
anahata
anahata's picture

That's ingenious, if complicated, but worth a thought.

Anahata www.treewind.co.uk West Yorkshire, UK