Tutorial: wordpress security

Time to start the discussion about how to secure wordpress blogs.

There are some actions everyone should take to secure his wordpress blog:

  1. Strong passwords
    I use openssl to generate passwords:

    openssl rand -base64 60
    

    Change the number of digits too.

  2. Limit login attempts
    There is a plugin doing the job.
    It blocks the lightweight attacks. Because a botnet or someone using Tor does have a lot of IPs.
    Best feature: This plugin is sending you email warnings if such attacks happen.
    wordpress1.png

    Another plugin (thanks Abdussamad) to limit the number of login attemts: Fail2ban plugin.
    This plugin is creating log entries that can be catched by fail2ban.

  3. Password protect wp-admin directory
    htaccess/htpasswd are your friends.

  4. Never ever use common usernames
    No "admin", no "Admin", no "root", no "Administrator", not your nickname, not the domain name, well I guess you got it.

  5. Add some filters
    Ensure that wordpress is not telling everyone that the user exists but the password was wrong:

    nano /wp-content/your-theme/functions.php
    add_filter('login_errors',create_function('$a', "return null;"));
    
  6. Disable xml-rpc, if you do not need it
    Another filter:

    add_filter( 'xmlrpc_enabled', '__return_false' );
    

    Yup, xmlL-rpc is enabled by default since wordpress 3.5.
    And of course there is a plugin for that.

  7. Rename wp-login.php
    Nice catch from eva.
    There is a plugin that is able to rename the permalinks of the wp-login.php.
    Nice way to let the attacker run/hit into empty space.

  8. Update your wordpress instance and backup your database

On request the lighttpd and apache config for the password protection:

  • lighttpd

    $HTTP["url"] == "/wp-login.php" {
      auth.backend = "htpasswd"
      auth.backend.htpasswd.userfile = "/etc/lighttpd/wordpress"
      auth.require = ("/wp-login.php" => (
         "method" => "basic",
         "realm" => "wordpress",
         "require" => "valid-user"
      ))
    }
    
    $HTTP["url"] =~ "^/wp-admin/" {
      auth.backend = "htpasswd"
      auth.backend.htpasswd.userfile = "/etc/lighttpd/wordpress"
      auth.require = ("/wp-admin" => (
         "method" => "basic",
         "realm" => "wordpress",
         "require" => "valid-user"
      ))
    }
    
    
  • apache

    
      AuthName "Restricted Wordpress-Area"
      AuthType Basic
      AuthUserFile ~/wordpress
      Require valid-user
    
    
    # Deny access to important files
    
      Order deny,allow
      Deny from all
    
    
  • ngix

    location = /wp-login.php {
       auth_basic "Restricted Wordpress-Area";
       auth_basic_user_file /etc/nginx/wordpress;
    
       include /etc/nginx/conf.d/fastcgi.conf;
    }