PART 2: INSTALL & CONFIGURE
PART 3: SECURITY ADMIN
PART 4: SECURITY EXTRAS
###############################
### PART 4: SECURITY EXTRAS ###
###############################
In "Security Extras", we look at additional security measures to compliment CSF.
This is not a manual on any of the following topics, but just some nice, easy inclusions for them. Further reading on the following topics is recommended.
CONTENT
- IP RESTRICTION
- HTACCESS
- WEB APP SECURITY
- WORDPRESS SECURITY
- FINAL NOTE
IP RESTRICTION
The biggest security boost you can make on a server, is to restrict access based on IP address. Think about it... if I limit access to a resource, to allow my IP address only, the whole world is locked out!
KeyHelp Login Security
KeyHelp has such a security feature for Administrators.
KeyHelp > SETTINGS > Configuration / Login & session
Restrict administrative access:
Here you can restrict the login for administrator accounts to one or more IPs or subnet addresses
KeyHelp User Panel enables a User to password-protect a directory:
KeyHelp User Panel > SECURITY > Directory Protection
CSF Restrictions
UI access is restricted by IP address: /etc/csf/ui/ui.allow
CSF can also restrict port access by Country Code:
Firewall Configuration (csf.conf) - SECTION:Country Code Lists and Settings
The Country Code restrictions can be placed on any service port.
CSF Port & IP Filters
In /etc/csf/csf.allow and /etc/csf/csf.deny you can add more complex port and
ip filters using the following format (you must specify a port AND an IP
address):
Code: Select all
tcp/udp|in/out|s/d=port|s/d=ip|u=uid
Broken down:
tcp/udp : EITHER tcp OR udp OR icmp protocol
in/out : EITHER incoming OR outgoing connections
s/d=port : EITHER source OR destination port number (or ICMP type)
(use a _ for a port range, e.g. 2000_3000)
(use a , for a multiport list of up to 15 ports, e.g. 22,80,443)
s/d=ip : EITHER source OR destination IP address
u/g=UID : EITHER UID or GID of source packet, implies outgoing connections,
s/d=IP value is ignored
The htaccess file, is the last of the Apache configs that gets processed. It allows fine-grained configuration, at the user level. A user with read/write access to the site root directory, can create/edit a file named ".htaccess".
Any directory may contain a .htaccess file, that applies directives to that directory.
The htaccess file can be used to restrict access by IP address, to any resource.
htaccess is a mostly neglected aspect of security - but it is capable of so much!
Apache has plenty of good documentation - fully searchable:
https://httpd.apache.org/docs/2.4/
Test
After making edits to .htaccess, its a good idea to visit the site, and test the usual functions. Error-causing directives should be isolated, and modified/removed.
Security Directives
KeyHelp already has some security directives included. Included here are directives that can further boost security. Some you can use as-is, others may need customisation. Many were extracted from wordpress plugin BulletProof Security, and are good for many uses.
Add to your .htaccess
Copy/paste/edit:
Code: Select all
### HTACCESS: SECURE ###
# DENY ACCESS TO PROTECTED SERVER FILES AND FOLDERS
# Modify these to match files you want to protect
RedirectMatch 403 \.(htaccess|htpasswd|errordocs|logs)$
<FilesMatch "^(wp-config\.php|php\.ini|\.user\.ini|readme\.html)">
Require all denied
</FilesMatch>
# ALLOW ONLY NECESSARY REQUEST METHODS - else 405 Method Not Allowed
# HEAD method may be removed, esp. for private sites/services
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD) [NC]
RewriteRule .* - [R=405,L]
# ALLOW ACCESS TO FILE IN RESTRICTED DIRECTORY
# allow access to a file, that is within a restricted directory
# Include in .htaccess of the restricted directory, at top
<Files admin-ajax.php>
Require all granted
</Files>
# RESTRICT ACCESS TO DIRECTORY BY IP ADDRESS
# Include in .htaccess of any directory
<RequireAny>
Require all denied
Require ip 1.2.3.4
Require ip 5.6.7.8/12
# If local server access to the directory is required
# add the following; include the server ip addresses (ipv4 & ipv6)
# Require local
# Require ip 9.10.11.12
# Require ip 2001:0db8:85a3:0000:0000:8a2e:0370:7334
</RequireAny>
# RESTRICT ACCESS TO FILE BY IP ADDRESS
<Files wp-login.php>
Require all denied
Require ip 1.2.3.4
Require ip 5.6.7.8/12
# If local server access to the file is required
# add the following; include the server ip addresses (ipv4 & ipv6)
# Require local
# Require ip 9.10.11.12
# Require ip 2001:0db8:85a3:0000:0000:8a2e:0370:7334
</Files>
# ===== BRUTE FORCE LOGIN PAGE PROTECTION =====
# Protects the Login page from SpamBots, HackerBots & Proxies
# that use Server Protocol HTTP/1.0 or a blank User Agent
# This is for Wordpress login. For non-wordpress
# remove/modify the next line - you can use any REQUEST_URI
RewriteCond %{REQUEST_URI} ^(/wp-login\.php|.*wp-login\.php.*)$
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{THE_REQUEST} HTTP/1\.0$ [OR]
RewriteCond %{SERVER_PROTOCOL} HTTP/1\.0$
RewriteRule ^(.*)$ - [F,L]
# WORDPRESS ONLY
# Block the Include-only 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>
# ===== Headers: Security & CORS - content-type: text/html =====
# HSTS should be set at KeyHelp > Domains / Edit domain > Security (tab)
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*" "expr=%{CONTENT_TYPE} =~ m#text/html#"
Header always append X-Frame-Options SAMEORIGIN "expr=%{CONTENT_TYPE} =~ m#text/html#"
Header set X-XSS-Protection "1; mode=block" "expr=%{CONTENT_TYPE} =~ m#text/html#"
Header set X-Content-Type-Options nosniff "expr=%{CONTENT_TYPE} =~ m#text/html#"
</IfModule>
# ===== Regex Match Exploits =====
# The following directives match many exploits - blocked before they even get a chance!
# These seem to work fine on all KeyHelp services.
# Note: Take care with these directives, as some may cause a loss of functionality on some php applications. Skip rules may be created, for them to bypass these.
RewriteCond %{HTTP_USER_AGENT} (havij|libwww-perl|wget|python|nikto|curl|scan|java|winhttp|clshttp|loader) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (;|<|>|'|"|\)|\(|%0A|%0D|%22|%27|%28|%3C|%3E|%00).*(libwww-perl|wget|python|nikto|curl|scan|java|winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) [NC,OR]
RewriteCond %{THE_REQUEST} (\?|\*|%2a)+(%20+|\\s+|%20+\\s+|\\s+%20+|\\s+%20+\\s+)(http|https)(:/|/) [NC,OR]
RewriteCond %{THE_REQUEST} etc/passwd [NC,OR]
RewriteCond %{THE_REQUEST} cgi-bin [NC,OR]
RewriteCond %{THE_REQUEST} (%0A|%0D|\\r|\\n) [NC,OR]
RewriteCond %{REQUEST_URI} owssvr\.dll [NC,OR]
RewriteCond %{HTTP_REFERER} (%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{HTTP_REFERER} \.opendirviewer\. [NC,OR]
RewriteCond %{HTTP_REFERER} users\.skynet\.be.* [NC,OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(http|https):// [NC,OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [NC,OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
RewriteCond %{QUERY_STRING} (\.\./|%2e%2e%2f|%2e%2e/|\.\.%2f|%2e\.%2f|%2e\./|\.%2e%2f|\.%2e/) [NC,OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} (http|https)\: [NC,OR]
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)cPath=(http|https)://(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*embed.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^e]*e)+mbed.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*object.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^o]*o)+bject.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^.*(\(|\)|<|>|%3c|%3e).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(\x00|\x04|\x08|\x0d|\x1b|\x20|\x3c|\x3e|\x7f).* [NC,OR]
RewriteCond %{QUERY_STRING} (NULL|OUTFILE|LOAD_FILE) [OR]
RewriteCond %{QUERY_STRING} (\.{1,}/)+(motd|etc|bin) [NC,OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} \-[sdcr].*(allow_url_include|allow_url_fopen|safe_mode|disable_functions|auto_prepend_file) [NC,OR]
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC,OR]
RewriteCond %{QUERY_STRING} (sp_executesql) [NC]
RewriteRule ^(.*)$ - [F,L]
If you administer a site, and have access as user "root", you can lock down htaccess even more.
Change the ownership/permissions of .htaccess, to prevent modification by others:
(Replace $USER with the username, replace $DOMAIN with site root directory)
Code: Select all
cd /home/users/$USER/www/$DOMAIN
chmod 404 .htaccess
chown root:root .htaccess
WEB APP SECURITY
Web application security is often neglected. Good security uses a multi-layered approach - OS security, permissions/ownership, Apache directives/htaccess, firewall rules, restricted ip access, web app controls/restrictions, limit logins, file scanning, etc.
The htaccess directives above, especially "Regex Match Exploits", will definitely help to protect most web apps.
Your web app may have security features/plugins available - definitely worth a look.
Examples of good security plugins, appear below under "WORDPRESS SECURITY".
robots.txt
Placed in the domain's root directory, the robots.txt file contains directives for search bots. Resources are either allowed, or disallowed access to. This is a softer option than blocking.
If you have a private website, that you would like to keep OFF the major search engines:
1. Create robots.txt at site root
2. Add this text into it (disallows search indexing):
Code: Select all
User-agent: *
Disallow: /
WORDPRESS SECURITY
These are the best Wordpress security plugins I have found. Covered from every angle!
NinjaFirewall
NinjaFirewall is a true Web Application Firewall. Monitors for changed files, bots, XSS/PHP/SQL exploits and more. You can export/import settings for use on other websites. Nice compliment to CSF.
WP Bruiser (no-Captcha anti-Spam)
Eradicates comment spam, protects website forms - uses a token that bots don't get.
This is the best anti-spam for form input.
Limit Login Attempts Reloaded
Limits Wordpress login attempts and blocks abusive ip addresses.
Note: This job may be assigned to CSF instead, by using the WP Fail2ban Redux plugin, and creating some regex for CSF.
FINAL NOTE
If you followed the instructions carefully, you should now be running a powerfully configured CSF, with robust security. If you have problems, questions, or comments, post a reply here.
You can never be too rich, too good looking, or too secure!
Enjoy the journey...
- George