Like the blog? Get the book »

How to Secure Your New WordPress Installation

How to Secure Your New WordPress Installation

One of the best ways to ensure strong security for your WordPress-powered site is to secure its foundations during the installation process. Of course these techniques can be implemented at any point during the life of your site, but stetting them before the game starts prevents headaches and saves time. We’ll start with the WordPress database..

Step 1 – Setting up a secure database

Because the database is associated with virtually everything you do on your site, it is best to perform any modifications before configuring your options, installing plugins, and adding options. During the installation process, there are some effective ways of increasing the overall security of your WordPress site.

One of the first things that you can do to bolster security is to setup a proper database, user, and password. First, create the table that will be used for your WordPress installation:

CREATE DATABASE `wordpress`;

Now we need a user to go with that database. The key here is to create a user with only the required permissions. Enter the following SQL query to create a user that will have access only to the wordpress from the local server:

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON wordpress.* TO 'wpuser'@'localhost'
IDENTIFIED BY 'password';

By requiring that the user access the database from the local server only, we mitigate the possibility of remote database attacks. Further, by granting the user access to only the wordpress database, we ensure that other databases will remain safe should an attacker gain access.

Once the database and user have been setup, install WordPress as normal and continue with the next step.

Step 2 – Setting up a secure configuration file

There are two things we want to do with the wp-config.php file: implement Authentication Unique Keys and change the default database prefix. Let’s do it..

Implement Authentication Unique Keys

Directly after your MySQL database credentials in the wp-config.php file, you have the option of specifying a set of Authentication Unique Keys. These keys improve WordPress’ authentication system, providing strong security to your site. It is highly recommended that you take advantage of this feature.

/**#@+
 * Authentication Unique Keys.
 *
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/ WordPress.org secret-key service}
 * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
/**#@-*/

To do so, visit the official secret-key generation service and paste the results into your config.php file (replace the four lines beginning with “define”).

While you are you setting up the WordPress configuration file, you also may want to go ahead and optimize performance and implement some other choice configuration tricks.

Change the default database table prefix

While in your wp-config.php file, take a few moments to change your default database table prefix. By default, it’s “wp_”, but this is a well-known fact of which attackers and automated scripts take full advantage. By changing the table prefix to something unknown/random, you are using security through obscurity to help mitigate SQL-injection threats.

/**
 * WordPress Database Table prefix.
 *
 * You can have multiple installations in one database if you give each a unique
 * prefix. Only numbers, letters, and underscores please!
 */
$table_prefix = 'wp_';

In your wp-config.php file, locate the above lines and change the table prefix to something random or difficult to guess. I like to include the letters “wp” within the new prefix to help me identify tables specific to WordPress. For example, I might change it to something like, “wp_i337”.

Step 3 – Setting up a secure administration

Once you have finished with your database and configuration file, it’s time to setup a secure WordPress Admin area. We can do this by changing the default Admin username and protecting the wp-admin directory.

changing the default Admin username

By default, all WordPress installations have a default Admin username of, creatively enough, “admin”. As with the default database prefix, this fact is well-known to attackers, who target the admin account with password brute-force attacks. Thus, changing the username of your Admin account will help mitigate this potential vulnerability. To do so, execute the following SQL query on your WordPress database via phpMyAdmin:

UPDATE wp_users SET user_login = 'digwp' WHERE user_login = 'admin';

Your default Admin username is now changed to whatever you specified in the query. In this example, your new username will be “digwp”, so you will probably want to change it to something that is more difficult to guess.

Additionally, make sure that the password for the Admin account is as strong as possible. Use a random mix of uppercase and lowercase letters, and throw in a few underscores and numbers for good measure.

Protecting the wp-admin directory

All of the administrative files for your WordPress site are contained in the wp-admin directory. By protecting this directory against unauthorized access, we greatly strengthen the security of our site. Depending on your particular needs, there are at least two ways to go about doing this. Let’s look at each of them.

Allow open access only to specific addresses

This method uses a few choice HTAccess directives placed in your site’s root .htaccess file:

# SECURE WP-ADMIN
<FilesMatch ".*">
 Order Deny,Allow
 Deny from all
 Allow from 123.456.789
</FilesMatch>

Once in place, this code will deny access to all visits from any IP address that is not listed. Simply edit the “Allow from” line with your actual address, and create additional lines for multiple IPs. You can then check that it’s working by visiting your Admin area via proxy service. This is an effective way of protecting your wp-admin directory, but you may prefer using a password-based method instead..

Password-protect

Another option for securing your Admin area involves implementing secondary password protection via basic HTTP authentication. This is an excellent way to lock things down while still enabling access by anyone with the password from anywhere on the Web. To set it up, we need to create a text file with your desired username/password, and then require the username and password via .htaccess file.

For the username/password text file, use a password-generation service and paste the results into a file named “.htpasswd” (without the quotes!) and place it in a secure location on your server, preferably above your “public_html” or root-web directory.

Once the password file is in place, create an .htaccess file for your wp-admin directory and add the following code:

# SECURE LOGIN PAGE
<IfModule mod_auth.c>
 AuthUserFile /full/path/.htpasswd
 AuthType Basic
 AuthName "Password Required!"
 Require username
</IfModule>

After editing the username and full server path to your password file, you’re good to go. Make sure to test that everything is working before cracking a beer.

Important note about protecting wp-admin

As you implement this method, keep in mind that the wp-admin directory is used by a number of plugins, scripts, and even users. For example, if you allow open registration to your visitors, they will be unable to access the registration pages if your admin directory is blocked. Another good example is the Subscribe to Comments plugin, which provides an admin page through which users may unsubscribe to comments. This ain’t gonna work if they can’t access the admin area.

Just the beginning..

Of course, when it comes to the security of your WordPress site, these techniques are merely the beginning. As you continue in your WordPress travels, you will discover many, many more ways to increase the security of your site. By implementing the methods presented in this article during the setup process, you will be strengthening the security of your site’s foundation, providing yourself a solid platform on which to build.

31 responses

  1. This is a really good article for setting up the initial database. But I think it would be even more helpful to show how to change the SQL prefix of wp_ to something else with an in-use database.

    That would be really helpful to those that don’t manipulate SQL themselves a lot.

    • Urda, SEO Egghead has a very simple plugin to do this for you.

      To do it manually, you’d have to export your database to your computer, open it up with a text editor, and do a find and replace for all instances of wp_ with something else…..like clRE83f_ or something.

      Then head over to the wp-config file and change the wp_ value listed in there to the one you changed it in.

      Upload your new database and you’re done.

      Always always always back up your database first. In fact, make a copy of the back up so you have a backup of the backup! LOL

  2. You can put wp-config.php a directory above the WP install. This is true even if WP is installed at the web root, and I’d reckon having the config above the web root is fairly secure. :P

    There is a plugin that can use SSL for wp-login.php and one to block access upon multiple failed login attempts.

    And then in functions.php you should always put remove_action('wp_head', 'wp_generator'); to take out that meta tag that tells everyone you’re running WP.

    • How would you go about relocating the wp-config file? I would be interested in that as I have a hosting account with many sites, where I can place files outside of their website with SSH

  3. @kylegetsspam: That has no use, as most people have a sentence like ‘Powered by WordPress’ in there theme and when looking in the sourcecode you can always see where the style and other information is coming from, like: domain.tld/wp-content/

  4. Thanx for this awesome post

  5. I’m sorry but i can’t commet in this post, so i comment here : it seems that the variable $postlink is not correct because for every attachment this variable return the same url. Is it normal?

  6. Wow, some really great info here. I can’t wait for the book.

    Also the link for the secret key generator is broken above, it is actually located at https://api.wordpress.org/secret-key/1.1/

  7. Security through obscurity is no security at all.

    • Thanks for the bold statement, Brad. I think I’ve heard that somewhere before..

    • I definitely disagree with that statement.

      Changing your database prefix to something other than wp_ could be considered security through obscurity.

      I’ve seen through email alerts I have set up that someone tried to hack into one of my blogs through SQL Injection. They tried “guessing” that my database prefix was wp_.

      They were wrong.

      And if it were wp_, they just may of had a chance at cracking in.

  8. Great wp-security rare topic

  9. The absolute top #1 thing to do is definitely to chmod 400 wp-config.php so that other users of your shared hosting cannot read it.

    • Excellent advice, Ozh – thanks :)

    • That sounds like good advice. I haven’t tried it yet though. You sure WordPress doesn’t have any issues with it?

      • It depends on your server configuration. 400 permissions for the wp-config.php means that only the user (i.e., server) is able to read (and only read) the contents of the file. Aside from 0 (no access), a 400 setting is the most restrictive permissions level possible. Unfortunately, depending on how users are set up on the server account, it may be too restrictive.

  10. Joe @ IrrationalDad

    I effing LOVE this site!! Quality posts, and easy to read. Keep it up!

  11. Jeff will you please tell me which plugin you are using which allows to reply a specific comment?-

  12. UPDATE wp_users SET user_login = 'admin', user_login = 'digwp';

    Uh, that changes every user’s name to digwp. (It’s also redundant, as it sets user_login twice.) That does work OK (technically) if you just installed WordPress, but only then.

    I think this is what you were shooting for:
    UPDATE wp_users SET user_login = 'digwp' WHERE user_login = 'admin';

  13. Hi Jeff,

    Once again another top notch post!

    Those people wanting to password protect wp-admin AND use Subscribe to Comments may find my Subscribe To Comments & Protected Wp-admin Folder post useful.

  14. Andrew @ WeBuildYourBlog.com

    Thanks for sharing to us these techniques. It is informative and helpful. I hope you’ll get to post more regarding this topic.

  15. Nice tips! We also listed some small security tips on our blog at a week ago. Some vary from this list but some are the same. Funny that we had the same idea within a week. :)

  16. totally sweet!!!

    really really helpful stuff here. i didn’t really used to bother with protecting my sites cos i am new to it all and was just happy to get it up online. but now that i have got in to it all, this will be really useful if/when i end up making a wordpress site for a company, or in fact one for myself now that i am not such a noob.

    another awesome post. you’re like superman or something. clarke coyier? chris kent?

  17. wow just realised that it’s Jeff that posted it.

    sorry jeff, you deserve the praise and maybe i’ve just found a new webguy hero to worship!

    nice one mate!

  18. I have a quick question regarding protecting the wp-admin directory.

    Since I’m not a coding expert, would someone mind clarifying how the “/full/path/.htaccess” should be modified if I’ve placed the recommended .htaccess file above the public_html folder?

    My blog is in a directory immediately below the public_html folder. The public_html directory is in the root of the website. I hope I’m being clear enough!

    Thanks for your patience and help!

    Deb

  19. Thank you for sharing. Very useful tips.
    Will follow.

  20. un tres bon article, merci pour cet info .

Comments are closed for this post. Contact us with any critical information.
© 2009–2024 Digging Into WordPress Powered by WordPress Monzilla Media shapeSpace