Phplist: Difference between revisions

From Open Source Ecology
Jump to navigation Jump to search
No edit summary
(added commands to set permissions & ownership)
Line 25: Line 25:


* https://tech.michaelaltfield.net/2018/08/25/fix-phplist-500-error-due-to-random_compat/
* https://tech.michaelaltfield.net/2018/08/25/fix-phplist-500-error-due-to-random_compat/
=Proper File/Directory Ownership & Permissions=
This section will describe how the file permissions should be set on an OSE wordpress site.
For the purposes of this documentation, let's assume:
# vhost dir = /var/www/html/phplist.opensourceecology.org
Then the ideal permissions are:
# Files containing passwords (ie: config.php) should be located outside the docroot with not-apache:apache-admins 0040
# Files in the public_html/uploadimages dir should be apache:apache 0660
# All other files in the vhost dir should be not-apache:apache 0040
# All other directories in the vhost dir should be not-apache:apache 0050
This is achievable with the following idempotent commands:
<pre>
vhostDir="/var/www/html/phplist.opensourceecology.org"
wpDocroot="${vhostDir}/htdocs"
chown -R not-apache:apache "${vhostDir}"
find "${vhostDir}" -type d -exec chmod 0050 {} \;
find "${vhostDir}" -type f -exec chmod 0040 {} \;
chown not-apache:apache-admins "${vhostDir}/config.php"
chmod 0040 "${vhostDir}/config.php"
[ -d "${vhostDir}/public_html/uploadimages" ] || mkdir "${vhostDir}/public_html/uploadimages"
chown -R apache:apache "${vhostDir}/public_html/uploadimages"
find "${vhostDir}/public_html/uploadimages" -exec chmod 0660 {} \;
</pre>
Such that:
# the 'not-apache' user is a new user that doesn't run any software (ie: a daemon such as a web server) and whose shell is "/sbin/nologin" and home is "/dev/null".
# the apache user is in the apache-admins group
# the apache user is in the apache group
# any human users that need read-only access to the wordpress vhost files for debugging purposes and/or write access to the wp-content/uploads directory (ie: to upload large files that are too large to be handled by the web servers chain), then that user should be added to the 'apache' group
# any human users that need read-only access to the wordpress vhost files, including config files containing passwords (ie: wp-config.php), should be added to the 'apache-admins' group
# for anyone to make changes to any files in the docroot (other than 'wp-content/uploads/'), they must be the root user. I think this is fair  if they don't have the skills necessary to become root, they probably shouldn't modify the wp core files anyway.
==Why?==
The following explains why the above permissions are ideal:
# All of the files & directories that don't need write permissions should not have write permissions. That's every file in a wordpress docroot except the folder "wp-content/uploads" and its subfiles/dirs.
# World permissions (not-user && not-group) for all files & directories inside the docroot (and including the docroot dir itself!) should be set to 0 for all files & all directories.
# Excluding 'wp-content/uploads/', these files should also not be owned by the user that runs a webserver (in cent, that's the 'apache' user). For even if the file is set to '0400', but it's owned by the 'apache' user, the 'apache' user can ignore the permissions & write to it anyway. We don't want the apache user (which runs the apache process) to be able to modify files. If it could, then a compromised webserver could modify a php file and effectively do a remote code execution.
# Excluding 'wp-content/uploads/', all directories in the docroot (including the docroot dir itself!) should be owned by a group that contains the user that runs our webserver (in cent, that's the apache user). The permissions for this group must be not include write access for files or directories. For even if a file is set to '0040', but the containing directory is '0060', any user in the group that owns the directory can delete the existing file and replace it with a new file, effectively ignoring the read-only permission set for the file.


=Troubleshooting=
=Troubleshooting=

Revision as of 00:16, 16 September 2018

Phplist is a project for managing email lists. When OSE adopted it in 2018 for the OSE Newsletter, it was determined to be the most feature-rich FLOSS alternative to the gold-standard paid alternative, MailChimp.

Installation

Installation for phplist is relatively trivial. Their documentation leaves much to be desired, but it's fairly straight-forward.

libsodium

Note that, while not strictly a requirement on their website, phplist does effectively require libsodium and the corresponding pecl libsodium php extension to be installed on our OSE Server.

Without it, the random_compat library will throw an exception (which, by default, phplist will suppress from being written to the error logs):

[Thu Aug 23 00:06:29.560157 2018] [:error] [pid 17617] [client 127.0.0.1:51262] PHP Fatal error:  Uncaught exception 'Exception' with message 'There is no suitable CSPRNG installed on your system' in /var/www/html/phplist.opensourceecology.org/public_html/lists/admin/inc/random_compat/random.php:204\nStack trace:\n#0 /var/www/html/phplist.opensourceecology.org/public_html/lists/admin/defaultconfig.php(3): random_bytes(10)\n#1 /var/www/html/phplist.opensourceecology.org/public_html/lists/admin/index.php(103): require_once('/var/www/html/p...')\n#2 {main}\n  thrown in /var/www/html/phplist.opensourceecology.org/public_html/lists/admin/inc/random_compat/random.php on line 204

This, in part, is due to the use of 'open_basedir' in our /etc/php.ini file to whitelist the directories in which php is permitted to execute. The official response from the maintainers (see issue #99 of the random_compat repo on github [1]) is to simply add '/dev/urandom' to 'open_basedir' in '/etc/php.ini'. That didn’t seem like the wisest option, so--instead--we just install libsodium. Indeed, libsodium is the preferred source of entropy for random_compat, anyway [2].

yum install php-pecl-libsodium
httpd -t && service httpd restart

For more information about this issue and its fix, see

Proper File/Directory Ownership & Permissions

This section will describe how the file permissions should be set on an OSE wordpress site.

For the purposes of this documentation, let's assume:

  1. vhost dir = /var/www/html/phplist.opensourceecology.org

Then the ideal permissions are:

  1. Files containing passwords (ie: config.php) should be located outside the docroot with not-apache:apache-admins 0040
  2. Files in the public_html/uploadimages dir should be apache:apache 0660
  3. All other files in the vhost dir should be not-apache:apache 0040
  4. All other directories in the vhost dir should be not-apache:apache 0050

This is achievable with the following idempotent commands:

vhostDir="/var/www/html/phplist.opensourceecology.org"
wpDocroot="${vhostDir}/htdocs"

chown -R not-apache:apache "${vhostDir}"
find "${vhostDir}" -type d -exec chmod 0050 {} \;
find "${vhostDir}" -type f -exec chmod 0040 {} \;

chown not-apache:apache-admins "${vhostDir}/config.php"
chmod 0040 "${vhostDir}/config.php"

[ -d "${vhostDir}/public_html/uploadimages" ] || mkdir "${vhostDir}/public_html/uploadimages"
chown -R apache:apache "${vhostDir}/public_html/uploadimages"
find "${vhostDir}/public_html/uploadimages" -exec chmod 0660 {} \;

Such that:

  1. the 'not-apache' user is a new user that doesn't run any software (ie: a daemon such as a web server) and whose shell is "/sbin/nologin" and home is "/dev/null".
  2. the apache user is in the apache-admins group
  3. the apache user is in the apache group
  4. any human users that need read-only access to the wordpress vhost files for debugging purposes and/or write access to the wp-content/uploads directory (ie: to upload large files that are too large to be handled by the web servers chain), then that user should be added to the 'apache' group
  5. any human users that need read-only access to the wordpress vhost files, including config files containing passwords (ie: wp-config.php), should be added to the 'apache-admins' group
  6. for anyone to make changes to any files in the docroot (other than 'wp-content/uploads/'), they must be the root user. I think this is fair if they don't have the skills necessary to become root, they probably shouldn't modify the wp core files anyway.

Why?

The following explains why the above permissions are ideal:

  1. All of the files & directories that don't need write permissions should not have write permissions. That's every file in a wordpress docroot except the folder "wp-content/uploads" and its subfiles/dirs.
  2. World permissions (not-user && not-group) for all files & directories inside the docroot (and including the docroot dir itself!) should be set to 0 for all files & all directories.
  3. Excluding 'wp-content/uploads/', these files should also not be owned by the user that runs a webserver (in cent, that's the 'apache' user). For even if the file is set to '0400', but it's owned by the 'apache' user, the 'apache' user can ignore the permissions & write to it anyway. We don't want the apache user (which runs the apache process) to be able to modify files. If it could, then a compromised webserver could modify a php file and effectively do a remote code execution.
  4. Excluding 'wp-content/uploads/', all directories in the docroot (including the docroot dir itself!) should be owned by a group that contains the user that runs our webserver (in cent, that's the apache user). The permissions for this group must be not include write access for files or directories. For even if a file is set to '0040', but the containing directory is '0060', any user in the group that owns the directory can delete the existing file and replace it with a new file, effectively ignoring the read-only permission set for the file.


Troubleshooting

This section will provide hints for troubleshooting the phplist software. For general troubleshooting tips, also checkout the relevant documentation page on phplist.org's website here:

Enable error logging

By default, phplist will suppress errors from being written to log files. To fix this, find calls to error_reporting(0) and change them to error_reporting(1) in the phplist source code. For example, '/lists/admin/index.php' and '/lists/admin/init.php' [3]

See Also

References