After installing WordPress
Once the installation of your new WordPress site is complete, you should delete the administrator profile used during installation, create a new user with administrator permissions and all the user accounts you need.
Avoid weak usernames like „admin“ or „administrator“ (common in all WordPress installations) and remember to use a complex password. Disable pingback and trackback notifications on your admin panel (Settings > Comments), as they could constitute an access for Possible DDoS (Distributed Denial of Service) attacks on your website.
Protect your files from attacks and intrusions by adding the following lines of code in the .htaccess file, ideally at the beginning of the file in the root directory of your website:
#Deny folder listing
Options -Indexes
#Block access to sensitive files
<files .htaccess>
Order allow,deny
Deny from all
</files>
<files wp-config.php>
Order allow,deny
Deny from all
</files>
You should also block access to all unnecessary files by creating a new file .htaccess in the /wp-admin folder and adding the following lines of code:
#Block installation file
<files install.php>
Order allow,deny
Deny from all
</files>
<files setup-config.php>
Order allow,deny
Deny from all
</files>
Finally, have also a look at the robots.txt file located in the root folder of yours website. Check that it shows no sensitive informations about your WordPress installation, for example your administration folder wp-admin.
Change files and folders permissions
Make sure the files and folders in your WordPress installation have the appropriate permissions to prevent attackers to take control of your website.
You can change the permissions via an FTP client or via the panel administration provided by your web hosting service.
The following are commonly accepted as secure values:
- All folders should be set 755.
- All files should be set 644.
- wp-config.php should be set 600
- .htaccess should be set 604
Block PHP execution in your folders
Although WordPress installations block PHP file uploads by default through the administration panel, you should also block the ability to run PHP code in folders. Also, you should limit the execution of unnecessary PHP code in other folders used by WordPress which should not be accessed directly.
Create a new .htaccess file in your /wp-content/uploads folders, /wp-content/plugins and /wp-content/themes and add the following lines of code to block PHP executions:
<Files *.php>
deny from all
</Files>
Disable file editing in WordPress
This procedure aims to add a level of security to the administration panel, in order to prevent undesirable intrusions and limit errors made by authorized users. To disable the file editing option in the admin panel of WordPress, use the following line of code in the configuration file wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );
This code is equivalent to removing the „edit_themes“ permissions,
„edit_plugins“ and „edit_files“ for any registered user on the website.
You can add an additional level of control for active websites if you don’t want users to install themes and plugins on their own. Just enter the following code to the wp-config.php configuration file:
define( 'DISALLOW_FILE_MODS', true );
Remember to disable the command by changing the directive to „false“ if you have to perform WordPress installation tasks. All changes to the wp-config.php file must be inserted above the following line of code:
/* That's all, stop editing! Happy publishing. */
Always use HTTPS
The HTTPS protocol creates a secure connection between the users and the server, eliminating possible Man-in-the-Middle attacks (MITM). These attacks occur when an intermediate service alters or acquires information exchanged between two parties. That’s because HTTPS encryption is used for all sensitive data.
In order to use this protocol on your website, you must install an SSL certificate on your web server and change the URL in the admin panel. There are plenty of services and even free certificates provided with many hosing providers. One for all: Let’s encrypt SSL Certificate
There are also several WordPress plugins that can force an HTTPS connection on all the resources of your website to avoid warnings or errors during the display of HTTP and HTTPS content on the same page. Finally, you will have to force every new session in the website admin panel to use SSL protocol.
To do so, just enter the following code in the wp-config.php file:
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);
Disable session suggestions
As mentioned above, but it’s worth repeating, a good security policy is always to „give“ as little information as possible to the aggressors. This tip will help you to minimize the possible access to your website by disabling suggestions from the login page, which appear by default if the username or password are not correct:
function no_wordpress_login_errors() {
return "This website is protected.";
}
add_filter( 'login_errors', 'no_wordpress_login_errors' );
Change login access URL
Let’s face it: many attacks on websites do often target the login page. This is because bots are programmed to recognize a WordPress installation, add the path /wp-admin and access the administration area. Changing this default URL trunk will add an additional level of difficulty for the aggressors.
In the WordPress repository there are several plugins that allow you to change the location of your login page, for example mydomain.com/mynewadminurl.
The WPS plugin Hide Login is one of the most common used systems to perform this task. However, there are other plugins for this purpose and even many security systems also include this feature.
Use security headers
Improve your website security by implementing a series of HTTP headers integrated into the web server and sent to the browser.
Start with the X-Frame-Options heading, which prevents pages from opening in an external frame or iframe, thus preventing clickjacking attacks (literally „click theft“) on your website, a technique that leads users to disclose confidential information on a seemingly normal website.
By adding the following line of code to your .htaccess file, your website will tell the browser that frames can only be opened from the same domain or from the same domain origin:
Header set X-Frame-Options SAMEORIGIN
If your website integrates third-party services, you can specify that you deny access to the remaining ones. For example:
Header set X-Frame-Options "ALLOW-FROM https://example.com/"
Increase the protection of your website from XSS (cross-site scripting) attacks on older browsers by adding the following line of code to your .htaccess:
Header set X-XSS-Protection "1; mode=block"
In order to reduce the risk of XSS attacks, use the content-security-policy of the browser, which specifies what content on the website or third parties can dynamically load. For example, if you want your website to only accept content from same domain, add the following line of code to your .htaccess file:
Header set Content-Security-Policy "default-src 'self';"
In this way you will block the loading of scripts from external sources. For example, to change the variables for your specific project, use the following line of code to allow third-party scripts like Google Analytics:
header set Content-Security-Policy "script-src 'self' www.google-analytics.com;"
You should be careful when implementing this header because it is easy to block needed resources. I recommend to perform various tests with this header in a separate browser tab to check for any errors on the terminal.
Note: if you previously included the x-content-security-policy header in your server and has become obsolete, you will have to delete it because if you use both headers simultaneously you may have problems.
The fourth header that you can use to increase security is X-content-type-options, which protects your website from loading unwanted styles and scripts when the expected MIME types do not match those declared on the page. To add this protection, use the following line of code in your .htaccess file:
Header set X-Content-Type-Options "nosniff"
Prevent XML-RPC attacks
The xmlrpc.php file is used by some applications and software to communicate with WordPress; among these, the WordPress app or email clients like Outlook and Thunderbird that allow the „Publish articles via email“ feature. Also plugins like Jetpack or JSON API use the XMLRPC file for some of their functionality.
You can completely deny access to the xmlrpc.php file by modifying its rules in the .htaccess file or eliminating it directly if you are sure you don’t need it. To deny access via .htaccess, add the following lines of code to the file:
# Deny access to XMLRPC.
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
It is also possible to deny access to XMLRPC using plugins such as Disable XML-RPC or iThemes Security, mentioned in point 14.
For those who absolutely need this API feature, the best solution is to enable it only from the IP where you need to access and deny others. In this specific case, add the following lines of code to the file .htaccess, replacing the IP with the one from which you want to gain access:
<Files xmlrpc.php>
order deny, allow
deny from all
allow from X.X.X.X
</Files>
Disable JSON Rest API
If none of your plugins use the REST API, you can easily disable it. Just add the following lines of code to the functions.php file of your active theme or use a plugin: since WordPress version 4.4, REST APIs are included in the central core, allowing any developer to interact with the website. This allowed WordPress to reach a greater number of developers who do not have familiar with the platform, but at the same time left an open door to possible attacks, in particular DDoS attacks.
The following code blocks scripts from loading from external sources.
add_filter('json_enabled', '__return_false');
If you prefer not to tinker with the code, you can use the iThemes Security plugin, mentioned in point 12, or firewall plugins, which will keep the REST APIs active but will allow access only to users with exclusive permissions.
Remove any information about your WP installation
Another important thing, when it comes to WP security, is to hide as much informations as possible. For example, your current installed version is one of those info that can help an hacker to understand potential security holes, so by hiding this, attackers will not be able to exploit any known vulnerabilities associated with a specific version of WordPress.
You can delete information from the HTML header and static files by adding the following code to the functions.php file of yours theme or within the utilities of your plugin:
/*
Hide scripts and styles version
*/
function remove_wp_version_strings( $src ) {
global $wp_version;
parse_str( parse_url( $src, PHP_URL_QUERY ), $query );
if ( !empty( $query['ver'] ) && $query['ver'] === $wp_version ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
add_filter( 'script_loader_src', 'remove_wp_version_strings' );
add_filter( 'style_loader_src', 'remove_wp_version_strings' );
/*
Hide tag generator from headings
*/
function remove_wp_generator() {
return '';
}
add_filter( 'the_generator', 'remove_wp_generator' );
You can also hide informations about the current version of WordPress by adding the following line of code to the .htaccess file inside the main WP folder:
# Block any WP info
<files readme.html>
Order allow,deny
Deny from all
</Files>
<files license.txt>
Order allow,deny
Deny from all
</files>
Note: although some WordPress security guides recommend to delete all of these files, my advice is to completely block access to them, since a new wordpress installation or update will generate new ones.
Hide PHP notices and warnings
Along with other strategies to limit the information provided to attackers, it is a good idea to hide error reports, which can provide valuable information to attackers, like the PHP and WordPress versions of your website, folders structure or server informations.
In development environments, error reports are useful for validating your job and find potential errors; however, on an active website, you should disable these logs to hide informations such as paths, names, versions and more.
To disable error reports in WordPress, simply add the following lines of code to the wp-config.php file:
error_reporting( 0 );
ini_set( 'display_errors', 0 );
Hide any PHP /Apache information
The last tip for hiding informations is to configure the headers sent by the server: they often contain information about the software installed and the running PHP version.
Depending on the installation, you must hide or limit the informations shared on the web server by adding the following line of code to the .htaccess file in the main folder:
ServerSignature Off
There are two ways to hide informations about the PHP version of your website that some servers send in the HTTP header. First, add the following code to the .htaccess file:
Header unset X-Powered-By
Or use the following directive in the php.ini file:
expose_php = Off
Note: it is generally possible to add this line of code to the currently active php.ini file using the server administration panel, but the procedure
may vary depending on your hosting service.
Keep your WordPress up to date
In order to protect your website from known security vulnerabilities, you should always use the latest available version of WordPress, keep the installed plugins updated and update your themes.
Usually, keeping your website updated manually is preferrable, even if it requires more attention and time, because it allows you to check the included features in each update and their purpose. Regarding the order of updates, I always recommend updating the WordPress core first, then update plugins and themes without worrying about the order.
If, however, you want the WordPress core to be updated automatically, just add the following line of code to your wp-config.php file:
define( 'WP_AUTO_UPDATE_CORE', true );
If you want to update the plugins automatically, add the following line to
code to the functions.php file of your active theme:
add_filter( 'auto_update_plugin', '__return_true' );
Before adding this code, delete all unused plugins on your website. Simple deactivation is not enough to remove potentials vulnerabilities: eliminate them!
Adding the following line of code will automatically update the themes:
add_filter( 'auto_update_theme', '__return_true' );
Finally, remember that it is fine to keep your WordPress site safe, but you should not forget that your computer should also be protected by viruses and malicious software. Make sure you use a reliable and secure antivirus, keeping your operating system up to date.