User:Paul/sandbox/Server hardening

WARNING: This article is in a user sandbox, indicating it is a rough draft, and as such, is likely incomplete, contains buggy and insecure configurations, and is subject to substantial and frequent changes.

Changing site content tree permission
The permissions granted on site folders in the Install nginx article are somewhat insecure. This article explains how to create improved security on those directories.

Using  as owner and group of directories and files means that any process on the server running as that user or member of that group can edit and create those files and directories. So if a hacker somehow gains access to the server through an exploit, perhaps in a popular PHP package installed on the site, then the hacker will have a large degree of freedom to exploit the server.

A better method for managing security is to grant  write permissions only on those files and directories that are required for a given package to function properly. One way to accomplish this is to assign  as the owner of files and directories and   as the group. With permissions at  and   for directories and files, respectively, members of the the   group will still be able to conveniently edit and create files and directories.

However, it will be necessary to identify for each package which directories and files will require  to have write permissions. Ideally, any time  requires write permission to a directory, the directory should be locked down by nginx from running any type of code.

This will be easier to accomplish on some packages than others, and it may be that some research and testing will be required before a given package will function correctly. Additionally, tasks such as installing plugins and upgrading packages will likely require more work, with some additional research required for nearly every plugin installed.

Changing the content tree permission is relatively simple

username@servername:~$ sudo chown root:webdevs /var/www/example.com/ username@servername:~$ sudo chown root:webdevs /var/www/example.com/{backup,logs,private,public}

Using advanced permissions in WordPress
WordPress is one of the more difficult packages to manage using this permission set since blog admins will not be able to update WordPress, themes, and plugins or install or modify themes and plugins through the WordPress dashboard. The easier way to manage WordPress with this permission set is with SVN. Install the SVN tool, :

username@servername:~$ sudo aptitude install subversion

Install WordPress with SVN
username@servername:~$ sudo mkdir /var/www/example.com/public/blog username@servername:~$ sudo svn co https://core.svn.wordpress.org/tags/3.9.2 /var/www/example.com/public/blog/ username@servername:~$ find /var/www/example.com/public/blog -type d | xargs sudo chmod 775 username@servername:~$ find /var/www/example.com/public/blog -type f | xargs sudo chmod 664 username@servername:~$ mkdir /var/www/example.com/public/blog/wp-content/uploads username@servername:~$ sudo chown root:www-data /var/www/example.com/blog/wp-contents/uploads

Navigate to secure  https://www.example.com/blog  and complete the setup steps. Paste the contents of the file into the new  file:

username@servername:~$ sudo nano /var/www/example.com/public/blog/wp-config.php

The remaining parts of the install may now be completed through the browser.

Upgrading WordPress with SVN
The WordPress dashboard will alert admins that an update is available. Note the revision number of the update and enter it after  in the following   command and then run  :

username@servername:~$ sudo svn sw https://core.svn.wordpress.org/tags/ / /var/www/example.com/public/blog/ username@servername:~$ sudo php /var/www/example.com/public/blog/wp-admin/update.php

Note that, as with all updates of WordPress, the update will overwrite files created by WordPress, but will leave untouched the files created by users. If a file to be overwritten by the updater has been customized, save a copy and paste the customizations into the updated file. The update will never touch

Converting existing WordPress installation to SVN
If WordPress was installed as described in the Install WordPress article, then it can be converted relatively easily.

username@servername:~$ sudo mkdir /var/www/example.com/public/blog-svn

Install to the new directory the same version of WordPress that is to be converted to SVN (i.e., if 3.8.1 is already installed to the server, then install 3.8.1 to the new directory).

username@servername:~$ sudo svn co  https://core.svn.wordpress.org/tags/3.9.1  /var/www/example.com/public/blog-svn username@servername:~$ find /var/www/example.com/public/blog-svn -type d | xargs sudo chmod 775 username@servername:~$ find /var/www/example.com/public/blog-svn -type f | xargs sudo chmod 664 username@servername:~$ sudo cp -p /var/www/example.com/public/blog/wp-config.php /var/www/example.com/public/blog-svn/ username@servername:~$ sudo cp -rpfu /var/www/example.com/public/blog/wp-content/* /var/www/example.com/publc/blog-svn/wp-content

The last command will copy plugins, themes, images, and media that were added to WordPress. Note that any customized files created that were part of the WordPress core files will have to be customized again.

username@servername:~$ sudo chown -R root:www-data /var/www/example.com/public/blog-svn/wp-content/uploads username@servername:~$ sudo mkdir /var/www/example.com/backup/blog/ username@servername:~$ sudo mv /var/www/example.com/public/blog/ /var/www/example.com/backup/blog/WordPressTarArchive username@servername:~$ sudo mv /var/www/example.com/public/blog-svn /var/www/example.com/public/blog

Managing plugins with SVN
Managing WordPress plugins with SVN is a a little different from managing WordPress itself with SVN and requires some additional work to figure out where the developer has stuck the most recent version of the plugin. A plugin's SVN page can be found at  https://plugins.svn.wordpress.org/plugin-name/  - note that whenever a plugin has a space in its name, WordPress.org will substitute the space with a - in URLs. To get the latest version of the plugin, as listed on the plugin's home page ( https://wordpress.org/plugins/plugin-name/ ), first check  https://plugins.svn.wordpress.org/plugin-name/tags/  and see if the latest version number is listed in that directory. If it is listed there, simply download it using  to the plugins directory:

username@servername:~$ sudo svn propedit svn:externals /var/www/example.com/public/blog/wp-content/plugins/ username@servername:~$ sudo svn update /var/www/example.com/public/blog/wp-content/plugins/

If it isn't listed there, check the /trunk/ directory and see if it is possible to determine the latest version from readme.txt, notes in index.php</tt> or some other file that will indicate it is the latest version. Keep in mind that some developers will place development versions in the  directory, so it is not always a good idea to use this directory unless it is the only place to get the current stable version.

Using advanced permissions with MediaWiki
MediaWiki requires very few files or directories have write access. It is possible that some extensions will require additional write access, which may be documented in the extension's project page.

username@servername:~$ sudo chown -R root:webdevs /var/www/example.com/public/wiki/ username@servername:~$ sudo chown -R root:www-data /var/www/example.com/public/wiki/images/

Restricting database user permissions
Most packages using a database only require a few permissions during normal operations. The exception will be when changes are made to the core or plugins are installed. Database user permissions can be edited in phpMyAdmin.

Log in to phpMyAdmin with the MySQL root user account. Navigate to Users</tt> and under Database-specific privileges</tt> click Edit Privileges</tt> for the appropriate database. Check only SELECT</tt>, INSERT</tt>, UPDATE</tt> and DELETE</tt> in the DATA</tt> column and click Go</tt>.

When it is desired to make changes to a particular database, such as during a package upgrade or installation or upgrade of a plugin, simply log in to phpMyAdmin and edit privileges on the user to include all privileges except GRANT</tt>. After the operation is complete, return the user to only SELECT</tt>, INSERT</tt>, UPDATE</tt> and DELETE</tt> privileges.

It may be a good idea to remove a user's permissions on databases to which it has been assigned but have been archived.