In this tutorial I will teach you how to protect your WordPress site by implementing a basic Firewall.
This basic Firewall effectively blocks files that could be sources of problems, in case a vulnerability is found in the WordPress installation, in one of its plugins or themes.
The implementation of this Firewall requires access to your WordPress installation via a SFTP client or file explorer.
Now let’s look at everything you need to know to protect your WordPress site without a complex security plugin.
Table of Contents
- What Sites Should Use This Firewall?
- How to Prevent WordPress Sites from Getting Hacked
- First and Foremost : CloudFlare Firewall
- Mu-Plugins for WordPress Security
- A File for Exceptions: IP Addresses
- Theme and Plugins Editors, Plugin Installation, and Theme Lockdown
- Mu-Plugin to Stop PHP Execution in WordPress Folders
- Super Firewall MU – Plugin: Version #1
- Considerations
What Sites Should Use This Firewall?
This basic firewall is initially aimed at users who have a website that is not an E-Commerce or a membership site, as those type of sites require a series of exceptions for customers and users.
WordPress sites that function as authority sites or niche sites and that do not require their users to interact with WordPress installation files in any way shape or form can take full advantages of the simplicity of this plugin.
How to Prevent WordPress Sites from Getting Hacked
When setting up WordPress for the first time, it’s easy to overlook potential factors that could make your WordPress site vulnerable to hacking.
Primarily, hackers tend to focus on three key areas:
- WordPress Installation via Dashboard
- SFTP or SSH Access
- Database Vulnerabilities
If you’re using a reputable hosting provider, they likely have measures in place to prevent attempts at points 2 and 3.
For instance, Cloudways takes a robust approach by blocking unauthorized Database, SFTP and SSH access, managing exceptions through IP address exclusions.
In other words, you can rest assured that any potential hacking of your WordPress site won’t come from the database or the access to your installation via SSH/SFTP.
Using this hosting provider exposes your site only to attacks directed at the WordPress dashboard. In other words:
- Brute Force Attacks
- SQL Injections
- XSS Attacks
- Other vulnerabilities present in Plugins, Themes, and the WordPress core
Therefore, the security solution aims to address these issues.
First and Foremost : CloudFlare Firewall
It’s impossible for me to write about WordPress security without mentioning CloudFlare.
These are three rules you should have in place to protect your WordPress from all kinds of attacks
- I recommend writing a rule that whitelist specific files your site needs and be as specific as possible.
- Once you do that, write another rule to block every file and folder from your WordPress installation.
- Block common keywords used in XSS attacks and directory transversal attacks and SQL injections.
I think you can do a bit more but these three would prevent most attacks and malicious scans
Mu-Plugins for WordPress Security
My security mu-plugins currently consist of four files
Three files with functions and one file with variables and arrays for handling IP address exceptions.
Let’s get started.
A File for Exceptions: IP Addresses
The initial step is to craft a .php file holding an array featuring the list of IP addresses you don’t wish to restrict.
It’s a fairly straightforward file, and you’re free to name it as you like, but I’ll refer to it as “super-settings.”
Within this file, you’ll find an array where you should specify your IP addresses and your server’s IP to prevent any potential issues.
<?php
/*
Plugin Name: Super Settings
Plugin URI: https://wpsurfer.com
Description: Variable for Several mu-plugins
Version: 1.0
Author: TicoLibre
*/
//Allowed IP's
$allowed_ips = array(
'201.6.57.156',
'157.88.263.182'
);
You can add more IP addresses to whitelist other users and locations.
Theme and Plugins Editors, Plugin Installation, and Theme Lockdown
Here’s my first mu-plugin to add an extra layer of security to your site by limiting a hacker’s capabilities if they manage to infiltrate your WordPress dashboard.
Picture this: the hacker is inside your WordPress dashboard and realizes that:
- They can’t tweak files in the existing theme or others.
- They’re unable to tamper with files belonging to installed plugins.
Now, let’s say the hacker tries to install plugins from the WordPress repository or add a custom plugin to wreak havoc on your site. Surprise! They hit a roadblock:
- Uploading themes or plugins is not allowed.
- Deleting existing themes and plugin is not allowed
- Installing other themes and plugins is also not allowed
At this point, they’ll notice these restrictions are thanks to mu-plugins.
This mu-plugin can only be removed using a file explorer plugin or via SFTP or SSH access ( He can’t do either one of them).
Now, the hacker’s only option is to inject malicious scripts through posts or in media files.
<?php
/*
Plugin Name: PHP File Modification Blocker
Plugin URI: https://wpsurfer.com
Description: Deactivate the plugin and theme editor and prevent theme and plugin modifications
Version: 1.0
Author: TicoLibre
Author URI: https://wpsurfer.com
*/
// Allowed IPS
include 'super-settings.php';
// Disallow File Edit
define( 'DISALLOW_FILE_EDIT', true );
// Check if the client's IP matches any allowed IP
if (!in_array($_SERVER['REMOTE_ADDR'], $allowed_ips)) {
define('DISALLOW_FILE_MODS', true);
} else {
// Allow file mods since the request is coming from an allowed IP
define('DISALLOW_FILE_MODS', false);
}
This file will remove the file and theme editors functionality from your site and prevent the update, modification, and installation of plugins and themes.
It will also restrict WordPress updates unless you are connected using the IP addresses specified in super settings.
Mu-Plugin to Stop PHP Execution in WordPress Folders
This is another plugin with functionality that you might find in security plugins.
This mu-plugin essentially automatically adds an .htaccess file in the following folders:
- Plugin
- Themes
- Upload
The content in those .htaccess files is as follows:
<Files *.php>
deny from all
</Files>
Those three lines prevent the execution of PHP in folders, directories that should not contain .php files, or at least not in the root of those folders.
This mu-plugin not only creates those files automatically but will also add them in case they are removed or modified.
<?php
/*
Plugin Name: Disable PHP Execution
Plugin URI: https://wpsurfer.com
Description: Disable PHP Execution on Uploads, Theme, and Plugins Folder
Version: 1.0
Author: TicoLibre
Author URI: https://wpsurfer.com
*/
// Prevent direct access to this file.
if (!defined('ABSPATH')) {
exit;
}
function custom_prevent_php_execution()
{
$htaccess_content = "<Files *.php>\n";
$htaccess_content .= "deny from all\n";
$htaccess_content .= "</Files>";
$upload_dir = wp_upload_dir();
$plugins_dir = WP_PLUGIN_DIR;
$themes_dir = get_theme_root();
$directories = array($upload_dir['basedir'], $plugins_dir, $themes_dir);
foreach ($directories as $directory) {
$htaccess_file = trailingslashit($directory) . '.htaccess';
// Check if the .htaccess file exists
if (file_exists($htaccess_file)) {
// If the .htaccess file exists, read its content
$existing_content = file_get_contents($htaccess_file);
// Check if the content has changed before overwriting
if ($existing_content !== $htaccess_content) {
file_put_contents($htaccess_file, $htaccess_content);
}
} else {
// If the .htaccess file doesn't exist, create it with the specified content
file_put_contents($htaccess_file, $htaccess_content);
}
}
}
add_action('init', 'custom_prevent_php_execution');
If a hacker exploits a vulnerability and uploads a .php file in those directories, that .php file will not be able to be executed.
Super Firewall MU – Plugin: Version #1
This plugin is a firewall for WordPress designed to protect against a variety of threats. It works by checking the requested URI and query string for specific patterns associated with potentially malicious activity.
The plugin includes a list of forbidden patterns for both the request URI and query string, and if a match is found, it triggers a 403 Forbidden response.
<?php
/*
* Plugin Name: Firewall
* Plugin URI: https://wpsurfer.com
* Description: A super-fast firewall that protects WordPress against a wide range of threats.
* Version: 1.0
* Author: TicoLibre
* Author URI: https://ticolibre.com
*/
if (!defined('ABSPATH')) die();
function firewall() {
$variables_path = dirname(__FILE__) . '/super-settings.php';
if (file_exists($variables_path)) {
include $variables_path;
$request_uri_array = array(
'\.php', '\.zip', '\.rar', '\.bak', '\.bat', '\.htacc', '\.tar', '\.env', '\.tgz', '\.7z', '\.sql', '\.xz', '\.yml', '\.aws', '\.alfa', '\.zlib', '\.bk', '\.bz2', '\.dat', '\.gz', '\.py', '\.jsp', '\.asp', '\.cgi', '\.bash', '\.dll', '\.hg', '\.git', '\.cfg', '\.mdb', '\.htpas', '\.pass', '\.out', '\.cmd', '\.swp', '\.exe', '\.ini', '\.phtml', '\.md', '\.axd', '\.log', '\.sqlite', '\.hash', '\.cfm'
);
$query_string_array = array(
'script', 'password', 'user', 'union', 'select', 'from', 'cast', 'convert', 'concat', 'api', 'pass', 'mod', 'shell', 'eval', 'panel', 'char', 'passwd', 'login', 'where', 'config', 'pwd', 'md5', 'domain', 'flush', 'author=', 'alert'
);
$request_uri_string = '';
$query_string_string = '';
if (isset($_SERVER['REQUEST_URI']) && !empty($_SERVER['REQUEST_URI'])) $request_uri_string = $_SERVER['REQUEST_URI'];
if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) $query_string_string = $_SERVER['QUERY_STRING'];
$matches = array();
// Check if the IP is excluded
$client_ip = $_SERVER['REMOTE_ADDR'];
if (in_array($client_ip, $allowed_ips)) {
return; // Do nothing and allow the request for allowed IPs
}
// Continue with the existing checks for non-allowed IPs
if ($request_uri_string && preg_match('/'. implode('|', $request_uri_array) .'/i', $request_uri_string, $matches)) {
firewall_response($matches);
}
if ($query_string_string && preg_match('/'. implode('|', $query_string_array) .'/i', $query_string_string, $matches)) {
firewall_response($matches);
}
}
}
add_action('plugins_loaded', 'firewall');
function firewall_response($matches) {
do_action('firewall_response', $matches);
$matches = isset($matches[0]) ? $matches[0] : null;
if ($matches && apply_filters('firewall_match_logging', false)) error_log('Firewall: '. $matches);
$header_1 = apply_filters('firewall_header_1', 'HTTP/1.1 403 Forbidden');
$header_2 = apply_filters('firewall_header_2', 'Status: 403 Forbidden');
$header_3 = apply_filters('firewall_header_3', 'Connection: Close');
header($header_1);
header($header_2);
header($header_3);
exit();
}
The firewall allows for excluding certain IP addresses from these checks.
Considerations
These are some considerations before implementing this super security plugin:
- I am not a developer or programmer; I know enough to achieve my goals. Often, I modify existing snippets or take code from existing plugins. I use artificial intelligence assistance to modify code or address some errors I encounter in the plugins I use
- Mu-plugins may benefit from improvements and may require adjustments with each WordPress update. These plugins do not have irreversible effects.Use the plugins included in this and any other publication with caution and at your own risk.
- For me, these mu-plugins serve as a fallback; I implement security rules at the CDN level, so this plugin is only in case something goes wrong with Cloudflare. Conduct tests on staging sites, less critical sites, or test sites before using some of the mu-plugins mentioned here.
- I don’t see these plugins being installed on client sites as they require maintenance and administration.