WordPress Security

Since the number of WordPress sites has grown tremendously, there are things which need to be done to make sure that the blog site and the data are not compromised and if they are, how to fix the problem. The following information is from information that I have put together while working WordPress compromises over the past few years and I hope that it helps everyone to be able to stop issues before they arise.

 

Keep in mind that some of the steps below can be used within other Content Management Systems (CMS) such as Joomla and Drupal as well.

 

Table of Contents

 

  • Basic WordPress Security
  • WordPress Permissions
    • File Permissions
    • Folder Permissions
  • WordPress Brute Force Attacks
    • WordPress wp-login block using Fail2ban
    • Restrict Access To WordPress Admin Panel
  • Related articles

 

—===—===—===—

 

Basic WordPress Security

 

I put together a presentation on this subject which can be found is you click on – WordPress Security Presentation

 

There are things which can cause a content management system such as WordPress to become unstable or even compromised. One of the items which should be looked at is the release information of the WordPress installation. If the customer is unsure of the version or versions that they are running, the following will help find that out. Latest version as of this writing is 4.2.2. 

  • Run the following to find the version installed from within the web site document root folder – locate wp-includes/version.php | xargs -l1 grep -H “wp_version =”Ensure the all plugins and themes are up to date. This is something that the customer will need to do from within the WordPress Admin panel. WordPress is good at telling the administrator what needs to be updated.Do not use plugins from a place not associated with the WordPress site themselves. It is better to have the plugins verified by WordPress than not.A customer should be interested in locked down their WordPress instance and getting more our of security, so below is a list of plugins that will help with this.

 

 

Akismet – “Akismet is quite possibly the best way in the world to protect your blog from comment and trackback spam.”

Block Bad Queries – “Protect WordPress Against Malicious URL Requests”

Health Check = “Checks the health of your WordPress install” 

Spam Free WordPress = “Comment spam blocking plugin that uses anonymous password authentication to achieve 100% automated spam blocking with zero false positives”

Ultimate Security Checker = “Security plugin which performs all set of security checks on your WordPress installation”

WordPress File Monitor Plus = “Monitor your website for added/changed/deleted files”

WordPress Firewall 2 = “This WordPress plugin monitors web requests to identify and stop the most obvious attacks” 

 

—===—===—===—

 

WordPress Permissions

 

One the major issues that I have come across which contribute to most WordPress and soon to be server compromises are file and folder permissions. If a developer is doing to the initial installation, I have found that they will open up the permissions to 777 (-rwx, -rwx, -rwx) or maybe a little lower in order to get the work done, but forget to back them off to a more manageable level. In order to manage this better we need something like fastcgi, or php fpm installed on the server. By having one of these in place, the apache user should not be needed to make these sites work.

Icon

 

It is recommended the folder permissions are to be set to no more than 755 (-rwx,-rx,-rx) with the exception of folders inside of the wp-content folder which include uploads, themes, etc. Any folder inside should still be 755 (-rwx,-rx,-rx) but can be safely taken up to 775 (-rwx,-rwx,-rx) as long as the owner and group are not directly related to apache.

File permissions should be no more than 644 (-rw,-r,-r) through out the WordPress instance. There are some exceptions to this such as the .htaccess file and wp-config.php file.

  • Create a phpinfo.php page with the following

<?php

 

phpinfo();

 

?>

  • Check to make sure the fastcgi is installed and runningLook for the Server API Value which should be set to CGI/FastCGI

 

Once you verify that FastCGI is installed, it is time to make sure that the file and folder permissions are set correctly

 

—===—===—===—

 

Make sure that you get permission from the customer to make the following changes to their server as there may be a potential for any adverse affects to take place.

 

File Permissions

 

According to WordPress security, file permissions should be no more than 644 (-rw,-r,-r), below shows how to issue a mass file permissions change as long as apache is not an owner or group of the content.

  • Change directory to the web site document root where the WordPress installation existsBefore making the following change, issue  for i in `find * -type f`; do ls -alh $i; done >> filepermsThe current file permissions are held in the file called fileperms so that if something happens we can do a little magic and get the permissions set backIssue the following to do a mass file permission change: find * -type f -exec chmod -R 644 {} \; Once the change has taken affect, verify by issuing, for i in `find * -type f`; do ls -alh $i; done

Folder Permissions

 

According to WordPress Security, folder permissions should be no more that 755 (-rwx,-rx,-rx). As mentioned before, there are some folder which need more permissions than other though. The procedures for WordPress folder permissions are very similar to those in the file permissions section above. 

  • Change directory to the web site document root where the WordPress installation existsBefore making the following change, issue  for i in `find * -type d`; do ls -alh $i; done >> folderpermsThe current folder permissions are held in the file called folderperms so that if something happens we can do a little magic and get the permissions set backIssue the following to do a mass folder permission change: find * -type d -exec chmod -R 755 {} \;Once the change has taken affect, verify by issuing, for i in `find * -type d`; do ls -alh $i; done

The difference to this is to adjust other folders now than later. What I have done in the past is the following making sure to not go over 775 (-rwx,-rwx,-rx).

  • Change directory to the wp-content folder within the wordpress installationBefore making the following change, issue  for i in `find * -type d`; do ls -alh $i; done >> wpcontentpermsThe current folder permissions are held in the file called wpcontentperms so that if something happens we can do a little magic and get the permissions set backIssue the following to do a mass folder permission change: find * -type d -exec chmod -R 775 {} \;Once the change has taken affect, verify by issuing, for i in `find * -type d`; do ls -alh $i; done

I have a note that shows another way to handling permissions in a Plesk environment. Making this work Plesk is very easy as but there are some gotchas which can have some adverse affects if not careful. Adding apache to the psacln group within Plesk is a bad idea as it has its own security issues that come along with it. So it was brought up that you may want to change the default umask of Apache to 000 so all files it writes are written with 777 permissions. Then to change the wp-content directory and all directories below it to 777 permissions. 

  • To adjust the wp-content folder to 777 – find wp-content -type d -exec chmod 777 {} \; 

With this done, the FTP user of the site will be able to modify files created by Apache BUT Apache will NOT be able to modify files created or modified by the FTP user.  An attacker will only be able to write files in the wp-content directory but as I have mentioned before, I do not agree with having folders set to a world accessible status 777 (-rwx, -rwx, rwx). Instead, it is best to at least have things locked down to a more stable permissions set of 775 (-rwx, -rwx, -rx) and no higher.

  • To change the wp-content folder to 775 – find wp-content -type d -exec chmod 775 {} \;

 

—===—===—===—

 

WordPress Brute Force Attacks

 

What you may have noticed is that the apache access logs get filled with information about XMLRPC and wp-login login attempts from different parts of the world. This is common place any more while using WordPress as a CMS. There are some things that can be done in order to make sure that the blogs integrity is still in one piece while mitigating the attacks against the site. 

 

Most, if not all brute force attacks are automated in nature which means that these are automated by either compromised machines on the internet or scripts that have been kicked off by hackers knowing that a customer is using WordPress as their software of choice.

 

—===—===—===—

 

Make sure that you get permission from the customer to make the following changes to their server as there may be a potential for any adverse affects to take place.

 

WordPress XMLRPC Access Blocking

 

The WordPress XMLRPC file is used for API access to the administrative panel as well as access to the site via mobile devices. Lately, this has become a major issue of concern when it comes to WordPress security. The following will show how to stop this issue, at least for the mean time.  The following sends out a global 403 forbidden for any xmlrpc.php access attempt, keep in mind that this can be added on a per domain basis as well but if the customer is not using API and or mobile access, then global blocking is better. This change will take some time to fully work for existing traffic while new traffic will automatically be seeing the 403 information.

  • Edit the apache configuration file located in /etc/httpd/conf/httpd.confAdd the following anywhere in the configuration file. I will usually place it right above the virtual host entries

<IfModule mod_alias.c>

RedirectMatch 403 xmlrpc\.php

</IfModule>

  • Save the apache configuration fileRestart the apache service

 

WordPress wp-login block using Fail2ban

 

One of the biggest issue so far while looking at the web sites access logs are noticing wp-login brute force attacks that occur from locations all over the world. In order to help mitigate this issue, then there are some steps which need to be taken using applications such as Fail2ban and IPTables. These steps can be used on pretty much any linux platform.

  • Make sure that you have Fail2ban installed and workingEdit the jail file located in /etc/fail2ban/jail.conf and add the following content

    [wordpress-login]

    enabled = false
    filter = wordpress-login
    action = iptables[name=WordPressLogin, port=http, protocol=tcp]
    logpath = /var/www/vhosts/*/statistics/logs/access_log
    maxretry = 5
    ban = 86400
  • Save the changes to the jail.conf fileSave the changes to the new WordPress Filter fileRestart the Fail2ban service with /etc/init.d/fail2ban restartCheck the IPTables Firewall to make sure that the wordpress-login jail shows in the list: iptables -L
  • Create a new filter for the WordPress Jail instance the you created above. The new file should be located in/etc/fail2ban/filter.d/wordpress-login.conf
  • # wordpress-login.conf
              [INCLUDES]
              before = common.conf

              [Definition]
              _daemon = wordpress
              failregex = ^<HOST>\ \-.*\”POST\ \/wp-login.php HTTP\/1\..*\”
              ignoreregex =

 

Restrict Access To WordPress Admin Panel

 

In order to make sure that that the customer has the access that they need to work on their WordPress instance even with the Fail2ban jail in place, then we can restrict access to wordpress instance by adding the following to the apache configuration file.

 

  • Edit the /etc/httpd/conf/httpd.conf and add the followingChange the x.x.x.x to an IP Address given by the customer

 

<LOCATION /wp-login.php>

order deny,allow

deny from all

# whitelist addresses

allow from x.x.x.x

allow from x.x.x.x

allow from x.x.x.x

</LOCATION>

  •  Save the /etc/httpd/conf/httpd.conf fileRestart the apache serviceHave the customer test that they can reach and log into their WordPress instance

 

—===—===—===—

 

Related articles

 

http://wpengineer.com/2484/xml-rpc-enabled-by-default-in-wordpress-3-5/

https://wordpress.org/plugins/disable-xml-rpc/

http://wordpress.org/latest.zip

 

 

—===—===—===—

—===—===—===—

Below is a link to a presentation that I put together for WordPress Security back when I worked at Rackspace Hosting.

 

WordPressSecurity01-Presentation.pptx

 

—===—===—===—

—===—===—===—

 

WORDPRESS SECURITY PLUGINS

 

https://wordpress.org/plugins/

 

Akismet – “Akismet is quite possibly the best way in the world to protect your blog from comment and trackback spam.”

 

Block Bad Queries – “Protect WordPress Against Malicious URL Requests”

 

Health Check = “Checks the health of your WordPress install” 

 

Spam Free WordPress = “Comment spam blocking plugin that uses anonymous password authentication to achieve 100% automated spam blocking with zero false positives”

 

Ultimate Security Checker = “Security plugin which performs all set of security checks on your WordPress installation”

 

WordPress File Monitor Plus = “Monitor your website for added/changed/deleted files”

 

WordPress Firewall 2 = “This WordPress plugin monitors web requests to identify and stop the most obvious attacks”

 

—===—===—===—

—===—===—===—

 

WP-LOGIN BLOCK

 

/etc/fail2ban/jail.conf

[wordpress-login]

enabled = false
filter = wordpress-login
action = iptables[name=WordPressLogin, port=http, protocol=tcp]
logpath = /var/www/vhosts/*/statistics/logs/access_log
maxretry = 5
ban = 86400

—===—===—
/etc/fail2ban/filter.d/wordpress-login.conf

[root@518485-app1 filter.d]# cat wordpress-login.conf
# wordpress-login.conf
[INCLUDES]
before = common.conf

[Definition]
_daemon = wordpress
failregex = ^<HOST>\ \-.*\”POST\ \/wp-login.php HTTP\/1\..*\”
ignoreregex =
http://www.fail2ban.org/wiki/index.php/Whitelist

[DEFAULT]

# “ignoreip” can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
# ban a host which matches an address in this list. Several addresses can be
# defined using space separator.
ignoreip = 127.0.0.1/8

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>