Categories
Security Wordpress

Securing WordPress with .htaccess

Leaving your wp-login.php script or wp-admin folder accessible from the internet allows for bruteforcing of your passwords

My way of solving this is by creating a randomly named folder e.g. “asbra” with som php code that sets a cookie which is required by the .htaccess file.

<?php
    $admin_cookie_code="329847348597";
    setcookie("AsbraSession",$admin_cookie_code,0,"/");
    header("Location: ../wp-admin/index.php");
?>

Then paste the following at the bottom of your .htaccess file

###############################
# BEGIN Asbra AB <j@asbra.nu> #
###############################

#
# Cookie based access to administration
#
<IfModule mod_rewrite.c>

    RewriteEngine On

    # Only allow admin if ASBRA Cookie has been set correctly
    RewriteCond %{REQUEST_URI} /wp-login.php
    RewriteCond %{HTTP_COOKIE} !AsbraSession=329847348597
    RewriteRule .* - [L,F]

    RewriteCond %{REQUEST_URI} /wp-admin
    RewriteCond %{HTTP_COOKIE} !AsbraSession=329847348597
    RewriteRule .* - [L,F]

    # Disable WordPress include-only files
    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]

    # Do we really need the Trace, Delete and Track Request Methods ? 
    RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
    RewriteRule ^(.*)$ - [F,L]

    # Block User ID Phishing Requests
    RewriteCond %{QUERY_STRING} ^author=([0-9]*)
    RewriteRule .* - [L,F]
    #RewriteRule .* http://example.com/? [L,R=302]

</IfModule>

#
# And then some extra file/uri security
#

# This stops hackers from trying thousands of passwords in only a few requests
<Files xmlrpc.php>
    order allow,deny
    deny from all
</Files>

<Files wp-cron.php>
    order allow,deny
    deny from all
</Files>

<Files wp-links-opml.php>
    order allow,deny
    deny from all
</Files>

<files ~ "^.*\.([Hh][Tt][Aa])">
    order allow,deny
    deny from all
</files>
 
<files wp-config.php>
    order allow,deny
    deny from all
</files>

# Are you using the REST API?
<files wp-json>
    order allow,deny
    deny from all
</files>

#
# Set extra headers for clients
#
<IfModule mod_headers.c>

    # nosniff - Blocks a request if the requested type is "style" and the MIME type is not "text/css", or "script" and the MIME type is not a JavaScript MIME type.
    Header set X-Content-Type-Options nosniff

    # Enable the cross-site scripting (XSS) filter in users browser
    Header set X-XSS-Protection "1; mode=block"

    # Require HTTPS (Be very careful! this is saved in the clients browser for 2 years!)
    # Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

    # Prevent Fraudulent Iframing
    Header set X-Frame-Options "SAMEORIGIN"

    # Add your own! Only allow includes from SELF and from CDN (Unsafe inline is needed if wee want inline javascript and CSS)
    Header add Content-Security-Policy "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: http://cdn.asbra.nu;"

    # Dont give away referer on outgoing links
    Header always set Referrer-Policy "same-origin"

    # Block client from certain features
    Header set Feature-Policy "microphone 'none';camera 'none';geolocation 'self';payment 'none';sync-xhr 'self'"

    # Unset headers revealing versions strings
    Header unset X-Powered-By
    Header unset X-Pingback
    Header unset SERVER

</IfModule>

################
# END Asbra AB #
################

We also want to limit the upload folder. Place this .htaccess in your wp-contents/ folder

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

And just in case someone gets a hold och your backend, limit their possibility to edit your files by placing the following at the end of wp-config.php

define('DISALLOW_FILE_EDIT', true);

WordPress will install minor updates automatically, to enable all core updates, including minor and major:

define( 'WP_AUTO_UPDATE_CORE', true );

 

By Nimpen J. Nordström

System Developer and Network Security Enthusiast

Leave a Reply

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