How to secure PHP for WordPress

WordPress is a Content Management System that runs on PHP and MySQL. It the most popular CMS used worldwide and as such, is targeted most by attackers. In a previous article, we have looked into how you can clean your WordPress site when it has been hacked.

Here, we look at how we can make the environment WordPress runs on, more secure to prevent the hack in the first place.

1. Update PHP

To protect against known vulnerabilities, update your PHP and PHP based packages to the latest versions. Avoid using PHPv5 and use version 7.2 and above. At the time of writing this article, PHP 7.3.12 is the latest version.

[root@serv0-rawle ]$ yum update php* -y

2. Restrict PHP information display

To do this, you need to turn off expose_php in php.ini file

expose_php=Off

Below is a sample output when expose_php is set to On

[mwabini@serv0-rawle etc]$ curl -I localhost
HTTP/1.1 302 Found
Date: Sat, 14 Dec 2019 16:45:21 GMT
Server: Apache/2.4.41 (Unix) OpenSSL/1.1.1d PHP/7.3.12 mod_perl/2.0.8-dev Perl/v5.16.3
X-Powered-By: PHP/7.3.12
Location: http://localhost/dashboard/
Content-Type: text/html; charset=UTF-8

Once turned Off, the X-Powered section is removed from the response as follows:

[mwabini@serv0-rawle etc]$ curl -I localhost
HTTP/1.1 302 Found
Date: Sat, 14 Dec 2019 16:53:25 GMT
Server: Apache/2.4.41 (Unix) OpenSSL/1.1.1d mod_perl/2.0.8-dev Perl/v5.16.3
Location: http://localhost/dashboard/
Content-Type: text/html; charset=UTF-8

Disabling expose_php ensures your web server does not confirm to the world that its running PHP

This move is further complemented by disabling the .php extension for your scripts so they are not visible at the address bar when URLs are accessed. To disable display of .php extension, add the following to a .htaccess or vhost

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]

3. Minimize PHP extensions

Only load PHP modules that are needed by your WordPress installation.

This improves your installations’ security and also performance.

To disable specific extensions, disable its configuration file in /etc/conf.d folder

4. Control file uploads on the site

If you don’t need your users to upload any files, turn off the ability to upload files. To do this, set file_uploads to off in php.ini

file_uploads=Off

If users need to upload files, limit the size of files and type of files uploaded.

file_uploads=On
upload_max_filesize=4K
post_max_size=10K

Don’t allow users to upload executable files on the website such as PHP scripts

5. Disable remote code execution

You will rarely need to have this on. Disable the allow_url_fopen and allow_url_include functions on your site. These make it possible to retrieve data from remote locations.

To disable these, set the following in php.ini file:

allow_url_fopen=Off
allow_url_include=Off

6. Disable harmful PHP functions

There are some PHP functions that can be used in a harmful way. They were designed for useful reasons but somehow allow exploit of PHP on the server and can be used to gain access or spam on your server. To disable these, set the disable_functions in php.ini as follows:

disable_functions = system, exec, shell_exec, passthru, phpinfo, show_source, highlight_file, popen, proc_open, fopen_with_path, dbmopen, dbase_open, putenv, move_uploaded_file, chdir, mkdir, rmdir, chmod, rename, filepro, filepro_rowcount, filepro_retrieve, posix_mkfifo

7. Control access of PHP to the file system

If PHP is used to just run your site, it doesn’t need to have access to all parts of your file system. Eg, if your site runs under /home/user/public_html, php doesn’t need to be enabled on /etc folder or even /home/user folder. You need to enable it only on the folder the site runs

To do this use the open_basedir directive as follows in php.ini file

open_basedir="/home/user/public_html"

If you need to enable PHP in various folders, specify this as follows

open_basedir="/home/user/public_html:/home/user/sub.domain.tld"

8. Set proper file, folder permissions and access rights All files and folders should not have more read, write and execute permissions than needed. For the WordPress config files (wp-config.php) you can set its permission t 0600 For system based config files such as /etc/php.ini, or /etc/my.cnf, set these to 0444. Also, prevent them from being edited using chattr command

chmod 0600 /home/user/public_html/wp-config.php
chattr +i /home/user/public_html/wp-config.php
chmod 0444 /etc/my.cnf
chattr +i /etc/my.cnf

Any directory that shouldn’t be accessed publicly can be using the following directives on .htaccess file or httpd.conf file

<directory / >
    Options None
    AllowOverride None
    Order allow,deny
</directory>

9. Install mod_security
Mod security is an Apache security feature that protects against Cross Site Scripting(XSS) and other attacks. XSS is the most common form of vulnerability on WordPress sites according to wordfence.com study

It can be prevented by writing secure PHP code. Incase code is not secure enough, Mod Security protects the site against this attack. To install and configure Mod Security, proceed as follows.

a. Run the command below to install Mod Security

[root@serv0-rawle~]$ yum install -y mod_security mod_security_crs

b. Access mod security config file using editor

[root@serv0-rawle ~]$ vim /etc/httpd/conf.d/mod_security.conf

Set SecRuleEngine as follows

SecRuleEngine On

c. Test Apache and Restart

[root@serv0-rawle ~]$ apachectl configtest
Syntax OK
[root@serv0-rawle ~]$ systemctl restart httpd

10. Install Suhosin for PHP 5

If you are using PHPv5, install Suhosin to harden your PHP.

However, its recommended to avoid PHPv5 and use higher version of PHP.

11. Log PHP errors instead of displaying them on site

A site visitor should not see errors when they visit your website. As such, avoid displaying the errors on the site and instead log them onto a log file

To do this, set the following in php.ini

display_errors=Off
log_errors=On
error_log=/var/log/phperrors.log

Have we missed any PHP security measure? Please let us know via the comment section below.

References

1. https://www.cyberciti.biz/tips/php-security-best-practices-tutorial.html

2. https://cheatsheetseries.owasp.org/cheatsheets/PHP_Configuration_Cheat_Sheet.html

3. https://www.owasp.org/index.php/Category:Attack

4. https://www.owasp.org/index.php/OWASP_Wordpress_Security_Implementation_Guideline

5. https://php.net/manual/en/security.php

Leave a Reply

Your email address will not be published. Required fields are marked *