11 WordPress .htaccess Security Rules – Prevent Hacking Without Plugins

Home » The Web » Wordpress, Themes and Plugin

For those with a hacked WordPress site, you will know that hackers tend to modify the .htaccess files and will redirect all traffic from Google to another url. Usually a php located in your wp-content/uploads folder. If you are using a VPS, if possible, disable .htaccess in Apache config and use the “Additional Apache directives” feature. Location of this feature varies from hosting panels.

See More ▼ 7 Best WordPress Firewall Preventing Hacks, SQL Injection And Brute Force

8 Useful .htaccess Snippets For Hardening Your WordPress Security And Prevent Hacking

Hayden James wrote an interesting topic on this issue – Apache Performance: Disable .htaccess. By disabling .htaccess, you improve the overall security and performance of your Apache server. If you are on a shared hosting, you do not have the ability to disable it, with that, you’ll have to harden your wordpress security by using a few codes. A quick summary.

  • Disable .htaccess via “AllowOverride None” improves security and server performance
  • Always Backup your .htaccess before making any dramatic changes.
  • .htaccess is not the only weak point when it comes to WordPress Security, always keep your WordPress updated and only use trust-able plugins/themes.
  • A good hosting also means better security features, more often than none, a shared hosting uses outdated software and comes with basic firewall, or none at all.

1. Implement The 6G Firewall

The 6G Firewall is entirely plug-n-play with no configuration required. It’s also open source, easy to use, and completely free, providing strong protection for any Apache-powered website.

To implement: include the entire 6G Firewall in the root .htaccess file of your site. Remember to backup your original .htaccess file before making any changes. Then test your pages thoroughly while enjoying a delicious beverage.

# @ https://perishablepress.com/6g/

</IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{QUERY_STRING} (eval\() [NC,OR]
    RewriteCond %{QUERY_STRING} (127\.0\.0\.1) [NC,OR]
    RewriteCond %{QUERY_STRING} ([a-z0-9]{2000,}) [NC,OR]
    RewriteCond %{QUERY_STRING} (javascript:)(.*)(;) [NC,OR]
    RewriteCond %{QUERY_STRING} (base64_encode)(.*)(\() [NC,OR]
    RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC,OR]
    RewriteCond %{QUERY_STRING} (</|%3C)(.*)script(.*)(>|%3) [NC,OR]
    RewriteCond %{QUERY_STRING} (\\|\.\.\.|\.\./|~|`|</|>|\|) [NC,OR]
    RewriteCond %{QUERY_STRING} (boot\.ini|etc/passwd|self/environ) [NC,OR]
    RewriteCond %{QUERY_STRING} (thumbs?(_editor|open)?|tim(thumb)?)\.php [NC,OR]
    RewriteCond %{QUERY_STRING} (\'|\")(.*)(drop|insert|md5|select|union) [NC]
    RewriteRule .* - [F]

</IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_METHOD} ^(connect|debug|move|put|trace|track) [NC]
    RewriteRule .* - [F]

</IfModule mod_rewrite.c>
    RewriteCond %{HTTP_REFERER} ([a-z0-9]{2000,}) [NC,OR]
    RewriteCond %{HTTP_REFERER} (semalt.com|todaperfeita) [NC]
    RewriteRule .* - [F]

</IfModule mod_alias.c>
    RedirectMatch 403 (?i)([a-z0-9]{2000,})
    RedirectMatch 403 (?i)(https?|ftp|php):/
    RedirectMatch 403 (?i)(base64_encode)(.*)(\()
    RedirectMatch 403 (?i)(=\\\'|=\\%27|/\\\'/?)\.
    RedirectMatch 403 (?i)/(\$(\&)?|\*|\"|\.|,|&|&?)/?$
    RedirectMatch 403 (?i)(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\")
    RedirectMatch 403 (?i)(~|`|</|>|:|;|,|%|\\|\{|\}|\[|\]|\|)
    RedirectMatch 403 (?i)/(=|\$&|_mm|cgi-|muieblack)
    RedirectMatch 403 (?i)(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ)
    RedirectMatch 403 (?i)\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$
    RedirectMatch 403 (?i)/(^$|(wp-)?config|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php

</IfModule mod_setenvif.c>
    SetEnvIfNoCase User-Agent ([a-z0-9]{2000,}) bad_bot
    SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot
    # Apache </ 2.3
    </IfModule !mod_authz_core.c>
        Order Allow,Deny
        Allow from all
        Deny from env=bad_bot

    # Apache >= 2.3
    </IfModule mod_authz_core.c>
            Require all Granted
            Require not env bad_bot

2. Disable PHP Execution In “uploads” Folder

Hackers loves to insert a backdoor files, usually the favorite location is the wp-content/uploads directory. There is no reason to have a .php files in that folder. Create a .htaccess file in /wp-content/uploads/ and copy paste the code. This will disable PHP execution within the folder.

# Kill PHP Execution
<Files *.php>
deny from all

3. Protect WordPress wp-config.php File

To protect your wp-config.php file from unathorized access, simply add this code to your .htaccess file.

<files wp-config.php>
order allow,deny
deny from all

4. Protect .htaccess From Unauthorized Access

To protect it from unauthorized access by hackers, you can stop them from accessing the file via this code.

<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all

5. Disable Directory Browsing In WordPress

There is no reason enabling directory browsing, not only it allows hackers to look into your site’s directory and file structure to find a vulnerable file, it is also bad for Google SEO as Google will index all of these files and folders. Many WordPress security experts recommend disabling directory browsing.

Options -Indexes

6. Block cross-site scripting (XSS)

The following code snippet protects your site against some common XSS attacks, namely script injections and attempts to modify global and request variables. Unless you use XSS, it is always a good idea to disable it.

# 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]

7. Restrict All Access To WP Includes

The /wp-includes/ folder contains the core WordPress files. There are no good reason for anyone to have access, including the owner and administrator. So to harden security it’s best to restrict all access to it.

# Blocks all wp-includes folders 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]

8. Restrict Direct Access To Plugin & Theme PHP files

As mentioned earlier, there is no reason for anyone else beside you to have access to the plugin and theme file, disabling directly calls is a good security policy.

# 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]

9. Access Only By IP

If you only access your WordPress admin area from the same location, you may want to limit access to your IP address only. To do this you’ll need to add a small snippet of code to the .htaccess file in the “wp-admin” directory. This method is not recommended if you do not have a static IP Address, meaning to say your ISP will assign you a new IP Address every time you restart your router.

order deny,allow
deny from all
allow from xx.xx.xx.xx

10. Secure Important Files

You could use .htaccess in WordPress to protect important files such as error logs, wp-config.php, and php.ini. For this, use the following snippet:

<FilesMatch "^.*(error_log|wp-config\.php|php.ini|\.[hH][tT][aApP].*)$">
Order deny,allow
Deny from all

11. Protect /wp-content/

To protect this folder from unauthorized access, create a separate .htaccess file in the wp-content folder. Next, copy and paste the below-mentioned snippet in the file:

Order deny,allow
Deny from all
<Files ~ ".(xml|css|jpe?g|png|gif|js)$">
Allow from all


  1. Gravatar
    mithun [ Reply ]

    Is the above .htacess tricks hampers with wordpress update option ?
    if i update my wordpress the can the above .htaccess tricks hamper or break the update process?

  2. Gravatar
    mithun [ Reply ]

    Is all the codes above have to be in the wordpress main htaccess file or i have to create an individual htaccess file for every folder?

    • Gravatar
      Ngan Tengyuen [ Reply ]

      just the main htaccess will do.

  3. Gravatar
    Gobinath [ Reply ]

    Order deny,allow
    Deny from all

    Allow from all

    after applying this code in wp-content folder site not loading, please help

  4. Gravatar
    Raphael Bolius [ Reply ]

    Thanks for the article!

    Just because it was mentioned above: All of that code must be written into the roots .htaccess. Only #02 has to be written in an additional .htaccess, as it is pointed out.

    But I have another question: If you are using plugins that write into the .htaccess (e.g. caching-plugins), In that case, I cannot use suggestion #04 that protects the .htaccess. Or can !?


  5. Gravatar

    I can’t find .htaccess. Please help me.

    • Gravatar
      TANK SHAKE [ Reply ]

      Because it starts with a period [.], it is hidden by default. You may need to check your settings of your SFTP client and make sure that “hidden” files and folders are visible.

  6. Gravatar

    If we do #10, then we don’t need to have #3 and #4, correct? Wp-config and .htaccess are already being protected by implementing the code you included in #10?

  7. Gravatar

    after putting all codes site not working

    • Gravatar
      Ngan Tengyuen [ Reply ]

      It depends on the server configuration, every server is different. Some code might works, some might not.

Leave a Reply

Your email address will not be published. Required fields are marked *