Skip to Main Content »

Search Site

You're currently on:

Security tips for your Wordpress website

Instructions of how to protect Wordpress from bots and hackers.


Five important steps to protect your Wordpress website from bots:


1) Change your admin login path. So nobody can find it.

2) Disable direct access to .php scripts on your website. Only the main "index.php" file should be available for everyone.

3) Block access to "xmlrpc.php" file if you don't use it.

4) Don't save backup files in the website root directory. Someone can find and download it.

5) Check regularly website raw access log. (few times per year is enough)



Steps in details:


1. Change your admin login path.


Add the following code:

to your .htaccess file:

RewriteRule ^admin22/?$ wp-login.php [NC,END]
RewriteRule wp-login.php - [NC,F]


to the "functions.php" file of your theme (or create a custom plugin):

$parts = explode("?", $_SERVER['REQUEST_URI']);
$dirs = explode("/", rtrim($parts[0], '/'));
$path = end($dirs);

$script = basename($_SERVER['PHP_SELF']);

if ($script == 'wp-login.php' && $path == 'admin22'){
  add_filter('site_url', '_wpadmin_filter', 10, 3);
}

function _wpadmin_filter($url, $path, $scheme) {
  return str_replace("wp-login.php", "admin22", $url);
}

add_filter('logout_url', '_custom_logout_url');
function _custom_logout_url($default) {
  return str_replace('wp-login.php', 'admin22', $default);
}

add_action('wp_logout','_auto_redirect_after_logout');
function _auto_redirect_after_logout(){
  wp_safe_redirect( home_url() );
  exit;
}

add_filter('login_url', '_hide_login_url');
function _hide_login_url($url){
  $url = home_url('?please_login=1');
  return $url;
}

add_action('init', '_display_session_expired');
function _display_session_expired() {
  if (isset($_GET['please_login'])){
    echo __( 'Session expired' ) . '. ' . __('Please log in again.');
    exit;
  }
}


Replace "admin22" with your custom path.


NOTE: Be careful with the ".htaccess" file! Any error in it will make your website not accessible.
Save a back up of it before changing.


After changing your admin login path don't think that bots will never find the new path.

So install some simple captcha plugin like:
https://wordpress.org/plugins/captcha-code-authentication

Or some simple plugin that can limit number of login attempts like:
https://wordpress.org/plugins/limit-login-attempts/

Or without a plugin:
https://stackoverflow.com/questions/25836668/wordpress-limit-login-attempts-without-plugins



There are also other different ways to protect you dashbord:

1. To change the admin path so nobody can find it.
That would be the best way. But wordpress requires string find-replace operations to make it work.
So it will affect website performance.

2. To rename the "wp-login.php" file.
You can find some instructions on this page:
https://stackoverflow.com/questions/45430027/changing-wp-admin-url-to-something-else

Also you will need to add some code into the "functions.php" file of your theme:
https://wordpress.stackexchange.com/questions/418230/unable-to-logout-correctly-after-wp-login-file-was-modified

3. To add a second layer of login, password protection with Basic Auth in htaccess.

You can find code examples on this page:
https://kb.planethoster.com/en/guide/protecting-your-wordpress-with-double-authentication-via-htaccess/
To allow logout from woocommerce:
https://wordpress.stackexchange.com/questions/352829/basic-auth-htaccess-on-wp-login-but-allow-logout-from-woocommerce

4. To limit access to admin dashbord by IP address:
https://stackoverflow.com/questions/51495232/how-can-i-restrict-access-to-the-wordpress-admin-login-page-by-ip-address-with


--- Sugested way: ---

If you need a stronger protection modify your login page.

Many websites were hacked just because they have exactly the same login page.

Just try to add a third field to the login page and no one bot or hacker will know what to do with it.



2. Disable direct access to .php scripts


In the access logs you can see that bots trying to call different files in the root folder like:
123.php
post.php

Also they are trying to access some plugin files directly.

You can deny access to them in the .htaccess file:

# deny access to all php scripts in the /wp-content directory
RewriteRule ^/?wp-content/.+?\.php - [NC,F]

# in the root allow only index.php and files that start with wp
RewriteCond %{REQUEST_URI} !^/(index|wp.+?)\.php
RewriteRule ^/?[^./]+\.php - [NC,F]

I have found it on this page:
https://stackoverflow.com/questions/25982250/htaccess-block-all-php-file-in-certain-directories


If some plugin requires direct access to its php file.
You can allow access to it by adding the line:
RewriteCond %{REQUEST_URI} !^/wp-content/plugins/plugin_name/some_file\.php$

before the line:
RewriteRule ^/?wp-content/.+?\.php - [NC,F]



3. Block access to "xmlrpc.php" file


"xmlrpc.php" file is needed to connect wordpress to other systems.
Bots are also interested in it. Because it is a way to get access to your website.
If your website is not connected to other systems. Or they don't connect via this file.

You can block access to it in .htaccess file:

# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order allow,deny
deny from all
</Files>


The code is from this page:
https://wordpress.stackexchange.com/questions/219643/best-way-to-eliminate-xmlrpc-php


4. Don't save backup files in the website root directory.


You will see from access logs that bots regularly check for back up files like:
backup.zip
website_backup.zip
database_08.03.22.sql.zip

So don't save your back up files in the website root where everyone can access it.


5. Check regularly website raw access log


Raw access log should be available in your cpanel or hosting administration panel.
It is long text file that contains only:
IP address, date, request type, requested URL, responce code, size of transmitted data, referrer and some other info.
Every line is a new request to the server.

A normal visitor makes many requests to load a single page.
Because it needs to load css styles, javscript scripts, images...

A bot makes just one request.
Because it does not need page styles and images.

Example of direct access from 61.136.144.96 :

87.116.777.55 - - [11/Sep/2023:09:31:52 -0500] "GET /favicon.ico HTTP/1.1" 200 1150 "/demo/wp/ymm/" "Mozilla/5.0" hottons.com 191.77.189.242
87.116.777.55 - - [11/Sep/2023:09:31:54 -0500] "GET /demo/wp/ymm/wp-content/plugins/ymm-search/ymm_ajax.php?action=ymm_selector_fetch&cId=0&values%5B%5D=BMW HTTP/1.1" 200 6 "/demo/wp/ymm/" "Mozilla/5.0" hottons.com 183.56.189.242
87.116.777.55 - - [11/Sep/2023:09:31:56 -0500] "GET /demo/wp/ymm/wp-content/plugins/ymm-search/ymm_ajax.php?action=ymm_selector_fetch&cId=0&values%5B%5D=BMW&values%5B%5D=X5 HTTP/1.1" 200 26 "/demo/wp/ymm/" "Mozilla/5.0" hottons.com 183.56.189.242
87.116.777.55 - - [11/Sep/2023:09:31:59 -0500] "GET /demo/wp/ymm/wp-content/plugins/ymm-search/ymm_ajax.php?action=ymm_selector_get_categories&values%5B%5D=BMW&values%5B%5D=X5&values%5B%5D=2006 HTTP/1.1" 200 265 "/demo/wp/ymm/" "Mozilla/5.0" hottons.com 183.56.189.242
87.116.777.55 - - [11/Sep/2023:09:33:06 -0500] "GET /demo/wp/ymm/README.html HTTP/1.1" 200 12089 "-" "Mozilla/5.0" hottons.com 183.56.189.242
61.136.144.96 - - [11/Sep/2023:09:47:02 -0500] "GET /pass.php HTTP/1.1" 403 - "-" "Mozilla/5.0" hottons.com 183.56.189.242
88.172.188.207 - - [11/Sep/2023:10:29:56 -0500] "GET /demo/wp/odp/wp-content/plugins/woocommerce/packages/woocommerce-blocks/build/style.css?ver=2.3.0 HTTP/1.1" 200 14729 "/demo/wp/odp/" "Mozilla/5.0" hottons.com 183.56.189.242
88.172.188.207 - - [11/Sep/2023:10:29:56 -0500] "GET /demo/wp/odp/wp-content/plugins/date-price-calendar/view/frontend/web/main.css?ver=5.2.18 HTTP/1.1" 200 343 "/demo/wp/odp/" "Mozilla/5.0" hottons.com 183.56.189.242
88.172.188.207 - - [11/Sep/2023:10:29:55 -0500] "GET /demo/wp/odp/ HTTP/1.1" 200 32360 "-" "Mozilla/5.0" hottons.com 183.56.189.242

If you have protected this part of your website the server response code will be 403 - forbidden or 404 - not found.
Response - 200 means that server still allows to access this script.



Long Story:


Hackers cannot check millions of wordpress websites.
They use bots (small programs, scripts) for it.
Bots check if a website has a back door accessible and record it.
Then another smarter program will try to break the back door.
If the back door is already open they will notify hacker or another programm that will add spam to your website.
Smart programs can add spam on such rare pages so the website owner will not notice it.
Or will use website to send spam to other people by email.

It is why the first step is to protect website from bots.

If your website is not new and already appears in google search results.
Bots also can find it.

Check the raw access log of website.
You will notice that some IP addresses are listed just once.
And they tried to access some .php script directly without loading page styles and images.

It is why you should protect .php scripts from direct access.

Now check the access logs more and you will see how bots trying to access some strange file:
wp-content/plugins/plugin_name/pub/static/upload_files.php
Why do they try to access it?
Because they know that file is a well known back door.

It is why you should check access logs regularly (few times per year is enough).
To see what they are looking for on your website and protect it.



Conclusion:


Safe life with Wordpress is possible. If you allow access only to the front-end and only for visitors not bots.