.htaccess Rules to Protect from WordPress SQL Injections

25th September 2019

Website Management Services UK WordPress SQL Injections

WordPress SQL Injections are a common hack method. Often used to insert malware and spammy links on your website. When it comes to protecting your WordPress site, this is a threat you need to be ready for! It’s hugely important to have a good WordPress security plan. In this post, I will explain in more detail what an SQL injection is and how you can minimise it happening to your website.

What are SQL injections?

Hackers can get into WordPress many ways, but as you might have guessed the name SQL injection does give us a clue as to how this hack is achieved or where it is targeted to be more precise.

WordPress Database Security

WordPress relies upon PHP and a MySQL database to function. A lot of your website’s data is stored in the MySQL database and is called upon when people visit your site. PHP code is used to call entries in the database.

How do people or bots hack the WordPress database?

In short, an SQL injection can happen anywhere you have a form element on your site. These can be:

  • Contact forms
  • Subscription forms
  • Login Forms
  • Search Bars and many other input fields.

Even the smallest of vulnerabilities can leave your database wide open to an SQL attack! Hackers basically look for sites with vulnerabilities, when they find one all they have to do is use a malicious SQL command instead of a valid form entry and that’s it there in!


Think about your contact form, for example. If you have a contact phone number field, then all you want people to put in there is numbers, no letters or other characters. If you do not properly set up your form field or your theme or plugin has neglected this then the hacker can put anything they like in that field, including malicious code!

SQL Injection Types

There are generally two main SQL injection types or more accurately two main reasons why the attackers use SQL injections.

To gain sensitive information – Classic SQLI

This kind of SQL injection basically returns sensitive information to the hacker’s browser. They will use forms on your site to query the database. This then reveals information about your database its structure and content. They can then use this information to launch an attack on your website.

To execute database actions – Blind SQLI

As the name suggests a blind injection is not looking to return any data as such, it’s looking to execute database actions like deleting, altering or adding tables.

You might find that you have been a victim of one or both WordPress SQL Injections, they may have deleted the wp_users table so now you can’t access the admin of your website. They may have gleaned sensitive information about your database and added malicious code, malware, spammy links, redirects and popups to your site.

Why doesn’t WordPress block this as standard?

WordPress as a platform is actually very secure, and they take this kind of security very seriously. WordPress release security and bug fix updates all the time. WordPress indeed does power around 34% of the internet now, which means its a big target for hackers that said WordPress do an excellent job at keeping its software secure.

The weak point is often themes and plugins, which is why a strict WordPress security and maintenance plan is essential. Plugins and themes get abandoned, or the authors are not that security conscious and don’t patch vulnerabilities very quickly. Take the RichReviews plugin with at this current time has been removed from the WordPress repository for not being secure. This was reported on by Wordfence and has been vulnerable for some time. The particular issue with this plugin is that it is open to XSS Via Unauthenticated Plugin Options Update. Hackers are exploiting this to inject malvertising code into sites. So as you can see, ensuring your site is secure and always up to date is massively important.

Its this that hackers often exploit. This is why we will always tell everyone to firstly have as few themes and plugins as possible and keep them updated at all times. If a theme or plugin is no longer supported or has not been updated for some time, we would suggest looking for an alternative.

How To Prevent SQL Injection

Before we go any further please make sure you take a backup of your database and site files. It’s very important you have a working copy of your site before making any changes, so in the event of breaking your site or something going wrong, you can easily restore it.

  1. Use Trusted Plugins and Themes

    As mentioned above, there are many ways hackers can get in, so ensuring you cover all bases is best. Use only trusted plugin and theme authors, NEVER use nulled or pirated plugins or themes!

  2. Ensure Your Hardware Is Secure

    Ensure the computer you use to access your site is also secure with the latest updates and anti-virus software.

  3. Make Sure Your Hosting Setup is Secure

    All too often people overlook the security of their hosting. Most go for cheap shared hosts with little care for your WordPress Security. No matter what you do elsewhere on your website, if your hosting and/or server are not secure then you are wasting your time.

  4. Keep Form Entry Fields To A Minimin & Properly Setup

    Form fields and input are the key access point for an SQL injection so use only what you need and ensure you set them up properly. If a field only requires a phone number then only allow that field to accept numbers.

  5. Use A Good Security Plugin and WAF

    It’s essential you use a good web application firewall (WAF) and Security monitoring plugin. These will often alert you to issues so you can to work fixing or blocking them before anything major happens. We recommend Wordfence or Sucuri but there are plenty of others.

  6. Utilise .htaccess Rules To Protect From WordPress SQL Injection

    If you are using an Apache server then you can use the .htaccess file to block some of the SQL injection attempts. This won’t 100% guarantee you never get attacked but can be useful in minimizing SQL injections.
    Below we have created a list of the best .htaccess rules to harden your WordPress website.

.htaccess Rules To Protect From WordPress SQL Injection & Harden WordPress

1. Redirect All Http to Https

If you have an SSL certificate then you might want to redirect all non-secure (HTTP) traffic to https. You can do this by adding the below code the .htaccess file in the root of your WordPress install. If you don’t have this file in the root you can create one then copy and paste this code into the file. Once you have done that save it and upload it to the root of your website.

#Redirect http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

2. Block Bad Bots

There are some bots known to be bad and should simply be blocked. Copy this code into your websites root .htaccess file.

#Block bad hackers
SetEnvIfNoCase User-Agent "^libwww-perl*" block_bad_bots
Deny from env=block_bad_bots

3. Disable Directory Browsing

Disable Directory Listing

If you don’t block directory browsing then hackers can simply enter in a URL like yourwebsite.com/wp-includes/ and see all your sites files and information. This is a big security risk and you should turn it off right away. You can do this by adding the following code to your roots .htaccess file.

# Disable directory browsing
Options All -Indexes

Once you have added that people who try to access these URLs will get a message like the one below.

Directory Browsing Forbidden

4. Deny Access To Files

Seeing as we are making all these changes to the .htaccess file it’s only sensible that we block access to it so no one can see what rules we have put in there! In addition, we should lock down a few other files like your wp-config file which holds all of your database login info!

Do this by adding the below to your sites root .htaccess file. This will block access to any .htaccess file anywhere in your site which is advisable.

# Deny access to all .htaccess files
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
 
# Deny access to readme.html
<files readme.html>
Order allow,deny
Deny from all
</files>
 
# Deny access to license.txt
<files license.txt>
Order allow,deny
Deny from all
</files>
 
# Deny access to wp-config.php file
<files wp-config.php>
order allow,deny
deny from all
</files>
 
# Deny access to error_log
<files error_log>
Order allow,deny
Deny from all
</files>

5. Block Access To wp-includes Folder And Files

The wp-includes folder is an important part of the WordPress software and holds the majority of your site’s files. That’s all this folder holds. Your own uploads, plugins and themes etc don’t go in there so really no one needs access to the wp-includes folder, not even you! Use the below code in your website roots .htaccess file to block access to the wp-includes folder and files.

# Deny access to wp-includes folder and files
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

6. Block cross-site scripting (XSS)

This code snippet block some common XSS attacks, mainly script injections and attempts to modify variables. Use the below code in your website roots .htaccess file to block these common XSS attacks.

# Blocks some XSS attacks
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} (\|%3E) [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]
</IfModule>

7. Restrict Direct Access To Plugin & Theme PHP files

Generally, there is no reason why anyone but you should need direct access to the plugin and theme files. This snippet disables direct calles to theme and plugin files. Simply add this to your website roots .htaccess file.

# Restricts access to PHP files from plugin and theme directories
RewriteCond %{REQUEST_URI} !^/wp-content/plugins/file/to/exclude\.php
RewriteCond %{REQUEST_URI} !^/wp-content/plugins/directory/to/exclude/
RewriteRule wp-content/plugins/(.*\.php)$ - [R=404,L]
RewriteCond %{REQUEST_URI} !^/wp-content/themes/file/to/exclude\.php
RewriteCond %{REQUEST_URI} !^/wp-content/themes/directory/to/exclude/
RewriteRule wp-content/themes/(.*\.php)$ - [R=404,L]

8. Protect Against SQL Injection

Last but not least is protecting against SQL injection in WordPress. It’s important to note again that this is not going to keep you 100% protected forever so don’t blindly use this code and think that’s it. You need to keep on top of your security monitoring all the time. This will however at least block some of the most common attempts at SQL injection. Insert this code into your roots .htaccess file.

# Protect Against SQL Injection
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC]
RewriteRule ^(.*)$ - [F,L]
RewriteCond %{QUERY_STRING} \.\.\/ [NC,OR]
RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]
RewriteCond %{QUERY_STRING} tag\= [NC,OR]
RewriteCond %{QUERY_STRING} ftp\:  [NC,OR]
RewriteCond %{QUERY_STRING} http\:  [NC,OR]
RewriteCond %{QUERY_STRING} https\:  [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>|ê|"|;|\?|\*|=$).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127\.0).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare).* [NC]
RewriteCond %{HTTP_COOKIE} !^.*WordPress_logged_in_.*$
RewriteRule ^(.*)$ - [F,L]
</IfModule>

9. PHP Code Execution Blocking With .htaccess Rules

In addition to the above rules, you can also stop PHP code execution within certain folders like your wp-content/uploads and wp-includes/ folders. Dependant on your theme and plugin setup these may work or may break certain things. You can try them and see how you go. If they result in errors just remove the file.

Block PHP Execution In wp-includes Folder

For this, you need to create a new .htaccess file with the below code. This file should then be uploaded to the wp-includes directory.

# Protect Against php execution
<Files *.php>
deny from all
</Files>

Block PHP Execution wp-content/uploads Folder

Generally, you shouldn’t have PHP code in your uploads folder as its there to store your images. The code below basically allows the below file types but does not allow PHP execution. Again this needs to be a new .htaccess file with the below code in then uploaded to wp-content/uploads directory.

# Disable access to all file types except the following
#Order deny,allow
#Deny from all
#<Files ~ ".(xml|css|js|jpe?g|png|gif|pdf|docx|rtf|odf|zip|rar)$">
#Allow from all
#</Files>

Full .htaccess File To Block Bad Bots, Access To Files & Block SQL Injection

For ease of use, below are all the rules discussed above for the root .htaccess file altogether. Remember the root .htaccess file goes in the root directory of your website (the same place as the wp-config.php file.)

##############################
#.HTACCESS FILE INFO BY 
#THRIVEWP.COM
##############################

#BEGIN https code
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

#BEGIN Block bad hackers
SetEnvIfNoCase User-Agent "^libwww-perl*" block_bad_bots
Deny from env=block_bad_bots

# Disable directory browsing
Options All -Indexes

# Deny access to all .htaccess files
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
 
# Deny access to readme.html
<files readme.html>
Order allow,deny
Deny from all
</files>
 
# Deny access to license.txt
<files license.txt>
Order allow,deny
Deny from all
</files>
 
# Deny access to wp-config.php file
<files wp-config.php>
order allow,deny
deny from all
</files>
 
# Deny access to error_log
<files error_log>
Order allow,deny
Deny from all
</files>

# Deny access to wp-includes folder and files
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

# Blocks some XSS attacks
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} (\|%3E) [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]
</IfModule>

# Restricts access to PHP files from plugin and theme directories
RewriteCond %{REQUEST_URI} !^/wp-content/plugins/file/to/exclude\.php
RewriteCond %{REQUEST_URI} !^/wp-content/plugins/directory/to/exclude/
RewriteRule wp-content/plugins/(.*\.php)$ - [R=404,L]
RewriteCond %{REQUEST_URI} !^/wp-content/themes/file/to/exclude\.php
RewriteCond %{REQUEST_URI} !^/wp-content/themes/directory/to/exclude/
RewriteRule wp-content/themes/(.*\.php)$ - [R=404,L]

# Protect Against SQL Injection
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC]
RewriteRule ^(.*)$ - [F,L]
RewriteCond %{QUERY_STRING} \.\.\/ [NC,OR]
RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]
RewriteCond %{QUERY_STRING} tag\= [NC,OR]
RewriteCond %{QUERY_STRING} ftp\:  [NC,OR]
RewriteCond %{QUERY_STRING} http\:  [NC,OR]
RewriteCond %{QUERY_STRING} https\:  [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>|ê|"|;|\?|\*|=$).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127\.0).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare).* [NC]
RewriteCond %{HTTP_COOKIE} !^.*WordPress_logged_in_.*$
RewriteRule ^(.*)$ - [F,L]
</IfModule>

Need help with this or WordPress Support and fixes?

Gavin Pedley

Gavin Pedley

Gavin is the guy behind the award-winning ThriveWP. He has over 18 years of experience creating, developing, hosting and managing WordPress websites.

Gavin regularly shares his expertise via the ThriveWP blog and Youtube channel, where he creates informative and helpful WordPress tutorial videos.

Connect with Gavin on FacebookLinkedin or Twitter.

Share this article

Subscribe to receive articles right in your inbox

Get Your Free Guide On Keeping Your WordPress Website Safe

Subscribe to learn how to keep your WordPress website safe, starting with this free guide. Unsubscribe with one click at any time.

We hate SPAM and promise to keep your email address safe. Here’s our privacy policy.

SEND ME MY FREE EBOOKS!​

Three amazing products that will enhance your website performance, ranking and maximise your income! Our eBook offer includes three eBooks in one bundle.

We hate SPAM and promise to keep your email address safe. Here’s our privacy policy.