Here are over-viewed few ways, involved into a complete mechanism, how to increase Apache2 security within Ubuntu 16.04.
Table of content:
- Security Assistant Script (SAS) ► Iptables
- Iptables – Basic Configuration – Save and Restore
- ModEvasive for Apache2
- ModEvasive ► SAS ► Iptables
- ModSecurity 2.9 for Apache2
- ModSecurity OWASP Core Rule Set 3.x
- ModSecurity Rules ► SAS ► Iptables
- ModSecurity Rules Whitelisting
- ModSecurity [and Apache] Log Files
- ModSecurity Log Files ► Fail2Ban ► Iptables
- ModSecurity GuardianLog ► HTTPD-Guardian ► SAS ► Iptables
- ModSecurity GuardianLog ► Custom Automated Analyse ► SAS ► Iptables
- HTTPS Connection (See also: Common Apache's Security Tips)
#Security Assistant Script (SAS) ► Iptables
Here is presented the script security-assistant.bash
. It could help you with the handling of the malicious IP addresses. The script has two modes.
Automatic mode - when an external program, as
mod_evasive
ormod_security
, etc., provides a malicious IP address. In this case, the syntax that invokes the script, should be:security-assistant.bash <ip-address> Guardian security-assistant.bash <ip-address> ModSecurity security-assistant.bash <ip-address> ModEvasive
In this mode the script provides two action stages and for every action it will send an email to the administrator(s).
First stage: for the first few 'transgressions' the source
$IP
will be banned for a period of time equal to the value of$BAN_TIME
. This mode uses the commandat
.Second stage: when the number of the transgressions from certain
$IP
becomes equal to the value of$LIMIT
, this IP address will be banned permanently.Manual mode - it has three options:
security-assistant.bash <ip-address>
--DROP "notes"
- creates an entry into the file/var/www-security/iptables-DROP.list
and generates a rule as:iptables -A GUARDIAN -s <ip-address> -j DROP
security-assistant.bash <ip-address>
--ACCEPT "notes"
- creates only an entry into the file/var/www-security/iptables-ACCEPT.list
.security-assistant.bash <ip-address>
--ACCEPT-CHAIN "notes"
- creates an entry into the file/var/www-security/iptables-ACCEPT.list
and generates a rule as:iptables -A GUARDIAN -s <ip-address> -j ACCEPT
The script uses iptables-save.sh
and the iptables
chain GUARDIAN
, explained into the next section. It will create and maintain few files within the $WORK_DIR
:
security-assistant.history
- contains the data for the previous IP's transgressions.security-assistant.mail
- the content of the last email sent by the script.iptables-ACCEPT.list
andiptables-DROP.list
.
###Installation
Create work directory, let's call it
/var/www-security
:sudo mkdir /var/www-security
Download
security-assistant.bash
and make it executable:curl https://pastebin.com/raw/wvV9B1nf | sed -e 's/\r$//' | sudo tee /var/www-security/security-assistant.bash sudo chmod +x /var/www-security/security-assistant.bash
Make
security-assistant.bash
available as custom command:sudo ln -s /var/www-security/security-assistant.bash /usr/local/bin/
Tweak
security-assistant.bash
. Change at least the value of the variable$EMAIL_TO
.
###Dependencies
sudo dpkg-reconfigure postfix
- send email, the minimal required configuration. If HTTPS is configured its TLS certificate can be used within the Postfix service.sudo apt install at
- seeman at
.
###Check-up
Represent yourself as
$AGENT
and check whether the Automatic MODE works properly:/var/www-security/security-assistant.bash 192.168.1.177 Guardian
Then check your e-mail, type
iptables -L GUARDIAN -n
, review the filessecurity-assistant.history
andsecurity-assistant.mail
. Run the above command 5 times and review the filesiptables-DROP.list
andiptables-CURRENT.conf
.Check whether the Manual MODE works properly - add your localhost to the White List:
security-assistant.bash 127.0.0.1 --ACCEPT "Server's localhost IP"
Then check the file
iptables-ACCEPT.list
.
###References
#Iptables – Basic Configuration – Save and Restore
###Basic configuration
sudo iptables -P INPUT DROP
sudo iptables -I INPUT 1 -i lo -j ACCEPT
sudo iptables -I INPUT 2 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
###Save and Restore
This could be achieved via custom scripts, that will save and restore the iptables
config during system's stop-start (or reboot) process. (If we using UFW to setup Iptables rules this step is not needed.)
printf '#!/bin/sh\n/sbin/iptables-save > /var/www-security/iptables-CURRENT.conf\nexit 0\n' | sudo tee /var/www-security/iptables-save.sh
printf '#!/bin/sh\n/sbin/iptables-restore < /var/www-security/iptables-CURRENT.conf\nexit 0\n' | sudo tee /var/www-security/iptables-restore.sh
sudo chmod +x /var/www-security/iptables-restore.sh /var/www-security/iptables-save.sh
sudo ln -s /var/www-security/iptables-save.sh /etc/network/if-post-down.d/iptables-save sudo ln -s /var/www-security/iptables-restore.sh /etc/network/if-pre-up.d/iptables-restore
###Create new chain
Create new chain, called GUARDIAN
and insert it as number 3 into the INPUT
chain:
sudo iptables -N GUARDIAN
sudo iptables -I INPUT 3 -j GUARDIAN
Reboot the system and check the configuration. Please note we must use sudo systemctl reboot
. Don't use the force option reboot -f
. When the system is back online we can check if the newly created chain exists by a command as: sudo iptables -L GUARDIAN -n
.
###References
- Iptables How To: Help Ubuntu | Digital Ocean
- Why does a valid set of Iptables rules slow my serverl? | Iptables status slow?
#ModEvasive for Apache2
ModEvasive is an evasive maneuvers module for Apache to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack. It is also designed to be a detection tool, and can be easily configured to talk to ipchains, firewalls, routers, and etcetera. Read more...
###Installation
Install and enable the module:
sudo apt install libapache2-mod-evasive sudo a2enmod evasive
Create Log Directory and make it accessible for
www-data
:sudo mkdir -p /var/log/apache2/mod_evasive sudo chown www-data /var/log/apache2/mod_evasive
Adjust the basic configuration – uncomment and edit certain directives in the file:
/etc/apache2/mods-enabled/evasive.conf
Restart Apache:
sudo systemctl restart apache2.service
.
###Check-up
- Open a web page from your server and refresh the browser window few times intensively (usually F5 can be used) - you must get 403 Forbidden error message (that will remains several seconds) and also, into the log directory, will be generated a new file.
###References
- Matt Brock's Blog: Security hardening on Ubuntu Server 14.04
- TechMint: Protect Apache Against Brute Force or DDoS Attacks
- GHub: Shivaas/mod_evasive | GHub: Jzdziarski/mod_evasive | HeliconTech: mod_evasive
#ModEvasive ► SAS ► Iptables
Here we will configure mod_evasive
to talk to iptables
through the security-assistant.bash
, created in the above section.
Grant permission to
www-data
to runsecurity-assistant.bash
without password viasudo
. Usesudo visudo
to edit safely/etc/sudoers
and add next line under the section# User privilege specification
:www-data ALL=(ALL) NOPASSWD: /var/www-security/security-assistant.bash
Edit
/etc/apache2/mods-available/evasive.conf
in this way:<IfModule mod_evasive20.c> DOSHashTableSize 3097 DOSPageCount 7 DOSSiteCount 50 DOSPageInterval 2 DOSSiteInterval 2 DOSBlockingPeriod 10 DOSWhitelist 127.0.0.1 #DOSEmailNotify [email protected] DOSLogDir "/var/log/apache2/mod_evasive" DOSSystemCommand "sudo /var/www-security/security-assistant.bash %s 'ModEvasive' >> /var/www-security/security-assistant-exec.log 2>&1" </IfModule>
Create log file and Restart the Apache server:
sudo touch /var/www-security/security-assistant.bash-exec.log && sudo chown www-data /var/www-security/security-assistant.bash-exec.log sudo systemctl restart apache2.service
To test this configuration we can simulate DDOS attack via the F5 method, mentioned above, or we can use a commands as ab
, hping3
, etc.
Attention: Be careful because the rule iptables -D INPUT -s $BAD_IP -j DROP
, used in the above script, will DROP all new connections from the source IP immediately, including yours SSH connection. So you need a backup way to connect to the server, during the tests. Or you can change this rule.
#ModSecurity 2.9 for Apache2
ModSecurity is a web application firewall engine that provides very little protection on its own. In order to become useful, ModSecurity must be configured with rules. In order to enable users to take full advantage of ModSecurity out of the box, Trustwave's Spider Labs is providing a free certified rule set for ModSecurity™ Core Rules provide generic protection. Read more...
###Installation
Install and enable the module:
sudo apt install libapache2-mod-security2 sudo a2enmod security2
Create configuration file:
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
Edit the configuration file and add or change at least directives:
SecRuleEngine On SecAuditLog ${APACHE_LOG_DIR}/mod_security2/modsec_audit.log SecGuardianLog ${APACHE_LOG_DIR}/mod_security2/modsec_guardian.log
Apply the Apache's configuration. The file
/etc/apache2/mods-enabled/security2.conf
involvesmod_security
configuration files into Apache's configuration. It shall looks as this:<IfModule security2_module> SecDataDir /var/cache/modsecurity IncludeOptional /etc/modsecurity/*.conf </IfModule>
Create Log Directory:
sudo mkdir -p /var/log/apache2/mod_security2
Setup log rotation:
sudo cp /etc/logrotate.d/apache2 /etc/logrotate.d/apache2-modsec
Then edit the new file in this way:
/var/log/apache2/mod_security2/*.log { … }
- Restart Apache:
sudo systemctl restart apache2.service
.
###Check-up
Create custom rule and test if it works. Edit
/etc/modsecurity/modsecurity.conf
and add these lines at the bottom:# Directory traversal attacks SecRule REQUEST_URI "../" "t:urlDecodeUni, deny, log, id:109"
Note: This is just an example, and it's covered by OWASP CRS.
Restart the server:
sudo systemctl restart apache2.service
. Then open your browser and typehttps://domain.name/?abc=../
or use one of these terminal commands:wget -L https://domain.name/?abc=../ curl https://domain.name/?abc=../
The result will be: 403 Forbidden. Check the logs:
sudo cat /var/log/apache2/mod_security2/modsec_audit.log
sudo cat /var/log/apache2/mod_security2/modsec_guardian.log
###References
- SpiderLabs/ModSecurity on GitHub: Reference Manual | FAQ
- ModSecurity HandBook, Ivan Ristic | ModSecurity 2.5, Magnus Mischel | 10 ways to im...
- HTBridge: Patching Complex Web Vulnerabilities Using ModSec | Path Traversal
- TechMint: Protect Apache Against Brute Force or DDoS Attacks Using ModSec
#ModSecurity OWASP Core Rule Set 3.x In Ubuntu 16 you can install **CSR 2.x**: `apt install modsecurity-crs`. More details about this approach can be fund in [this manual][31]. Here we will install [**CSR 3.x**][32], detailed instructions are provided within the [Installation manual][33]. [Git][34] is required: `sudo apt install git`.
###Installation
Clone CSR in the folder
/usr/share/modsecurity-crs.3
:sudo git clone https://github.com/SpiderLabs/owasp-modsecurity-crs /usr/share/modsecurity-crs.3
Future updating of the definitions:
cd /usr/share/modsecurity-crs.3 sudo git pull
Create configuration files:
sudo cp /usr/share/modsecurity-crs.3/crs-setup.conf.example /usr/share/modsecurity-crs.3/crs-setup.conf sudo cp /usr/share/modsecurity-crs.3/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example /usr/share/modsecurity-crs.3/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf sudo cp /usr/share/modsecurity-crs.3/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example /usr/share/modsecurity-crs.3/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
Read and edit these files carefully! Uncomment at least
SecGeoLookupDB
directive:SecGeoLookupDB util/geo-location/GeoIP.dat
Auto renew the GeoIP database, that is no longer included with the CRS. Instead you are advised to download it regularly. The script
util/upgrade.py
brings this functionality. You can use it as follows in cron -sudo crontab -e
:0 2 * * * /usr/share/modsecurity-crs.3/util/upgrade.py --geoip --cron
Apply the Apache's configuration. Edit
/etc/apache2/mods-available/security2.conf
in this way:<IfModule security2_module> SecDataDir /var/cache/modsecurity IncludeOptional /etc/modsecurity/*.conf IncludeOptional /usr/share/modsecurity-crs.3/crs-setup.conf IncludeOptional /usr/share/modsecurity-crs.3/rules/*.conf </IfModule>
Save the file and then restart Apache:
sudo systemctl restart apache2.service
.
#ModSecurity Rules Whitelisting
Whitelisting of ModSecurity Rules could be done via the ModSec directives:
SecRuleRemoveById, SecRuleRemoveByMsg, SecRuleRemoveByTag
SecRuleUpdateTargetById, SecRuleUpdateTargetByMsg, SecRuleUpdateTargetByTag
SecRuleUpdateActionById
These directives can be used system wide or within virtual host's configuration; also globally, for specific directories or location matches.
Disable
mod_security2
for phpMyAdmin. Change/etc/phpmyadmin/apache.conf
in this way:<Directory /usr/share/phpmyadmin> <IfModule security2_module> SecRuleEngine Off </IfModule> </Directory>
Disable specific rules for certain directory:
<Directory /var/www/html> <IfModule security2_module> SecRuleRemoveById 973301 </IfModule> </Directory>
Disable rules globally. For this purpose we must add our directives somewhere in Apache's configuration files. At this stage the bottom of
/etc/apache2/mods-available/security2.conf
(within the<IfModule>
tags) looks as good place.Disable rules within the entire Apache's configuration:
SecRuleRemoveById 973301 950907
Whitelist an IP address so it can pass through ModSecurity:
SecRule REMOTE_ADDR "@ipMatch 192.168.110.1" phase:1,nolog,allow,ctl:ruleEngine=Off,ctl:auditEngine=Off
Disable rules within Directory match:
<Directory /var/www/mediawiki/core> SecRuleRemoveById 973301 950907 </Directory>
Update rule's action by its ID within Location match:
<LocationMatch "/index.php.*"> SecRuleUpdateActionById 973301 "pass" SecRuleUpdateActionById 950907 "pass" </LocationMatch>
In the above examples we assume that 973301
and 950907
are rules IDs that obstruct the normal work of our web apps. We can find rules as these by an analyse of the file modsec_audit.log
, where at the bottom we will find entries that cantons strings as: [id "973301"]
and [id "950907"]
:
cat /var/log/apache2/mod_security2/modsec_audit.log | grep -Ewo 'id \"[0-9]{1,10}' | sed 's/id \"//' | sort -r | uniq
###References
- Sam Hobbs: Example Whitelisting Rules for Apache ModSec and the OWASP CRS
- SpiderLabs Blog: ModSec Advanced: Exception Handling
- NetNea: Handling False Positives with the OWASP ModSec CRS
- NetNea: Including OWASP ModSec CRS
#ModSecurity Rules ► SAS ► Iptables
Here are given few more examples how to create custom SecRules, also how we can call our Security Assistant Script (SAS) through them.
###Initial Setup
First we must create startup scrip. The reason is that, ModSec's exec
action has too simple syntax. So we can't use neither sudo
nor we are able to pass any parameters directly.
Create script file and -
security-assistant-modsec.sh
, make it executable forwww-data
:sudo touch /var/www-security/security-assistant-modsec.sh sudo chmod a+rx /var/www-security/security-assistant-modsec.sh
The script content shall be:
#!/bin/sh ATTACK_INFO="Our Server: $SERVER_NAME; Attacking IP: $REMOTE_ADDR; Attack. host: $REMOTE_HOST; Request URI: $REQUEST_URI; Arguments: $ARGS; Unique ID: $UNIQUE_ID" sudo /var/www-security/security-assistant.bash $REMOTE_IP ModSecurity "$ATTACK_INFO"
$REMOTE_IP
, etc. are EnvVars and their values will be filled by ModSec.
###Let's Rule
Redirect all
wp-admin
page requests, but except these from certain IPs (note thechain
):# Block wp-admin SecRule REQUEST_URI "^/wp-admin" "id:108, log, deny, t:lowercase, chain, redirect:https://www.you.." SecRule REMOTE_ADDR "!@ipMatch 192.168.1.11,99.77.66.12"
Update the default action of OWASP CRS 3 Directory traversal attacks rule:
# Directory traversal attacks SecRuleUpdateActionById 930110 \ "exec:/var/www-security/security-assistant-modsec.sh"
Create words black list:
# REQUEST_URI words blacklist (for complete words blacklist: SecRule REQUEST_URI|ARGS|REQUEST_BODY) SecRule REQUEST_URI "@pmFromFile /var/www-security/modsecurity-words-black.list" \ "id:150,\ deny,log,chain,\ redirect:https://www.you.." SecRule REMOTE_ADDR "!@ipMatchFromFile /var/www-security/modsecurity-ip-white.list" \ "setenv:REMOTE_HOST=%{REMOTE_HOST},\ setenv:ARGS=%{ARGS},\ exec:/var/www-security/security-assistant-modsec.sh"
In this example:
REQUEST_URI
- this variable contains the full URI from the current request.modsecurity-words-black.list
- contains list of phrases, where each specific phrase or word is placed into a new line. You can collect interesting words and phrases from theaudit.log
file.modsecurity-ip-white.list
- could contains white-list of IP addresses, separated at new lines. CIDR entries are acceptable.log
action will make log entry for this rule withid:150
.chain
action is equivalent of logicaland
, in the example with the combination of!
from the next chained rule we can read it asif not
.deny
action will block the request if it contains a phrase from theblack.list
(in its URI) and if theREMOTE_ADDR
is not listed into theip-white.list
.redirect
will redirect the request if the same conditions are met.deny
andredirect
actions belong toDisruptive
group of actions, that means they must be in the beginning of thechain
. Also they will be executed only when all chained rules reruntrue
.exec
action will call our external script. This action isn'tDisruptive
and will be executed when the current rule returns true. If it was it the begging of the chain it will be executed no mater the result of chained rules!setenv
action will export certain internal variables=%{...}
as env. vars, exported names can be different from the internals. Some variables must be exported manually, some other are exported automatically!?! Also for some vars, the manual export with the same names, for examplesetenv:REQUEST_URI=%{REQUEST_URI}
, will cause a blank value of the exported variable.
###References
- Executing shell scripts p.58 | Using Lua scripts with ModSec
- E.g.: Block IP | GeoIP | Multiple 404s | Block string | Redirection |
exec
onseverity
level
#ModSecurity [and Apache] Log Files
The Apache web server can be configured to give the server administrator important information about how it is functioning... The main avenue for providing feedback to the administrator is through the use of log files. Read more...
ModSecurity has powerful logging mechanism. By the directive SecGuardianLog
it provides a log feed specially designed to work with external scripts.
Currently the only tool known to work with guardian logging is
httpd-guardian
, which is part of the Apache httpd tools project. Thehttpd-guardian
tool is designed to defend against denial of service attacks. It uses theblacklist tool
to interact with an iptables-based... firewall, dynamically blacklisting the offending IP addresses. Read more...
###References
- Apache 2.4: Log Files | mod_log_config | ErrorLog Directive
- SudleyPlace: Apache Server Piped Error Logs
- The Art Of WEB: System: Analyzing Apache Log Files
#ModSecurity Log Files ► Fail2Ban ► Iptables
It is possible to setup Fail2Ban for data parsing of Apache's log files. modsec_audit.log
is probably the best choice, but see also the sections where we talk about of SecGuardianLog
.
Take care that SecAuditLogRelevantStatus
in /etc/modsecurity/modsecurity.conf
is commented. Otherwise everyone that receives a 404 error page would be blocked by fail2ban.
SecAuditEngine RelevantOnly
#SecAuditLogRelevantStatus "^(?:5|4(?!04))"
###References
- Fail2Ban Wiki: Apache | HOWTO fail2ban with ModSecurity2.5
- The Rietta Blog | OcpSoft | ModSec IP Tables
#ModSecGuardianLog ► HTTPD-Guardian ► SAS ► Iptables
httpd-guardian
- detect DoS attacks by monitoring requests Apache Security, Copyright (C) 2005 Ivan Ristic - is designed to monitor all web server requests through the piped logging mechanism. It keeps track of the number of requests sent from each IP address... httpd-guardian can either emit a warning or execute a script to block the IP address...This script can be used with Apache2 logging mechanism, or with ModSecurity (better).
###Installation and Setup within the Current Circumstances
Download
httpd-guardian
and make it executable:wget http://apache-tools.cvs.sourceforge.net/viewvc/apache-tools/apache-tools/httpd-guardian?revision=1.6 -O /var/www-security/httpd-guardian.perl chmod +x /var/www-security/httpd-guardian.perl
Change my $PROTECT_EXEC;
as follow to call our SAS script:
my $PROTECT_EXEC = "exec /var/www-security/security-assistant.bash %s 'Guardian' >> /var/www-security/security-assistant-exec.log 2>&1";
Optionally this customised mirrored version can be used:
curl https://pastebin.com/raw/EGCiY3TR | sed -e 's/\r$//' | sudo tee /var/www-security/httpd-guardian.perl chmod +x /var/www-security/httpd-guardian.perl
Apply the following change within Apache's configuration, then restart it:
#SecGuardianLog ${APACHE_LOG_DIR}/mod_security2/modsec_guardian.log SecGuardianLog "|/var/www-security/httpd-guardian.perl"
#ModSecGuardianLog ► Automated Analyse ► SAS ► Iptables
Here is presented a simple script, called apache-log-analyst.bash
, that isn't something special but could be a nice example. Its features are described within the script's body.
###Installation and Setup
Download
apache-log-analyst.bash
and make it executable:curl https://pastebin.com/raw/k4ejvc81 | sed -e 's/\r$//' | sudo tee /var/www-security/apache-log-analyst.bash chmod +x /var/www-security/apache-log-analyst.bash
Apply the following change within Apache's configuration, then restart it:
SecGuardianLog "|/var/www-security/apache-log-analyst.bash"
#HTTPS Connection
HTTPS is a communications protocol for secure communication over a computer network which is widely used on the Internet. HTTPS consists of communication over HTTP within a connection encrypted by TLS, or its predecessor SSL. Read more...
First enable SSL module if it is not enabled:
sudo a2enmod ssl
.Оpen port 443 (HTTPS) into the firewall.
Follow this manual and enable a free certificate from Let's Encrypt.
Check this answer and disable Weak Ciphers.
Then you can force all users to use HTTPS.