1. Don’t Display Error Messages on Failed Login
WordPress’ admin screen displays “ERROR: Invalid username.” if you enter an invalid username. But if you enter a valid username and an incorrect password, it’ll say “ERROR: Incorrect password.” This basic security flaw tells intruders which usernames to target. I don’t understand why the WordPress team designed it this way.
You can disable the error message by putting this in your theme’s functions.php
:
1
|
|
2. Publish Posts as a Non-Admin User
Create a WordPress user that has admin privileges and publish all posts as other users that are editor level and below. This makes it harder for intruders to guess which usernames have admin access.
3. Create A Plug-In To Protect Your Blog From Malicious URL Requests
Intruders often try malicious queries to probe website vulnerabilities. Put the following code in
a text file and save it as blockbadqueries.php
. Upload it to wp-content/plugins
and activate
it as you would any other plug-in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
4. Remove WordPress Version Number
WordPress automatically displays the version you are using in the head of your blog files. Intruders use this information to target known security holes, especially if you’re running older versions. Put this in your theme’s functions.php
:
1
|
|
5. Don’t Use Default “Admin” Username
Before WordPress 3.0, the default admin username was “Admin.” Can you spell “fail”? If you’re using an older version, run this SQL query:
1
|
|
6. Disable Directory Listing
By default, I disable directory listings. Put this either in your root .htaccess
or Apache’s site
config:
Options -Indexes
7. Separate Database User for WordPress Database
Create a separate database user just for WordPress and restrict its privileges to the relevant WordPress tables. If an intruder successfully cracks one WordPress installation, (s)he won’t take down your other databases.
8. Change Default WordPress Table Prefixes
Many published WordPress-specific SQL-injection attacks make the assumption that the table_prefix is “wp_”, the default. Changing this can block some SQL injection attacks.
9. Secure wp-admin with Apache
Password protect the admin area. Set AllowOverride All
in your Apache config and put this in
wp-admin’s .htaccess
:
# Secure wp-admin folder
AuthUserFile /var/www/apache/passwords
AuthType basic
AuthName "Some message here"
require user [user]
# This is the whitelisting of the ajax handler
Order allow,deny
Allow from all
Satisfy any
10. Secure wp-config
Deny web access to the wp-config folder by putting this .htaccess
in your document root:
# prevent others from accessing this file
order allow,deny
deny from all
# secure wp-config
order allow,deny
deny from all
11. Secure wp-includes
This goes in the same .htaccess
file as above:
# secure the wp-includes directory
RewriteRule ^wordpress/wp-admin/includes/ - [F,L]
RewriteRule !^wordpress/wp-includes/ - [S=3]
RewriteRule ^wordpress/wp-includes/[^/] .php$ - [F,L]
RewriteRule ^wordpress/wp-includes/js/tinymce/langs/. .php - [F,L]
RewriteRule ^wordpress/wp-includes/theme-compat/ - [F,L]
12. Protect against script injections
For the same .htaccess
file as above:
# protect against script injections
Options FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} () [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
13. Blacklist IP Addresses
If you notice certain IP addresses spamming you, you can instruct Apache to blacklist their
requests by putting this in a .htaccess
file in the root of your WordPress installation:
order allow,deny
allow from all
deny from [IP address 1]
deny from [IP address 2]
14. Database Backup
Make sure you use the WP-DBManager plugin to schedule regular backups and email the backup files to yourself, in case crackers break in and wipe out your database.
15. Prevent Hotlinking
This isn’t a security measure, but if you don’t want others hotlinking to your images, put this in
.htaccess
:
# deters content scrapers from hotlinking
RewriteEngine On
# modify next line accordingly
RewriteCond %{HTTP_REFERER} !^http://(. .)?davidxia.com [NC]
RewriteCond %{HTTP_REFERER} !^$
#Replace /images/nohotlink.jpg with your "don't hotlink" image url
RewriteRule .*.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]
Of course, this won’t stop them from simply taking your image manually, but at least now you won’t have to worry about them wasting your bandwidth.