Modsecurity
How to install ModSecurity
ModSecurity is a toolkit for real-time web application monitoring, logging, and access control.
CustomBuild allows you to install ModSecurity together with desired rulesets. The comodo ruleset will also install a plugin where you may manage rules from the DirectAdmin panel itself. The owasp is another rule provider available for automatic installation.
cd /usr/local/directadmin/custombuild
./build set modsecurity yes
./build set modsecurity_ruleset "comodo"
./build modsecurity
./build modsecurity_rules
./build rewrite_confs
ModSecurity Log Locations
/var/log/httpd
or:/var/log/nginx
Log files contained therein include:
modsec_audit.log
modsec_debug.log
The following directadmin.conf default setting specifies the modsecurity audit log location like so:
modsec_audit_dir=/var/log/modsec_audit
User controlled per-domain ModSecurity flags
This feature enables Users to skip some mod_security rules, or fully disable them when needed. Users can also view the per-domain logs via this interface and/or completely disable ModSecurity altogether.
How to disable the User's ability to use per-domain ModSecurity feature
Disabling the feature for all Users globally
Should you want to disable all Users' ability to use this feature, use the never commands feature, eg:
/usr/local/directadmin/direcadmin set never_commands CMD_MODSECURITY
service directadmin restart
Disabling the feature for a Single User
Should you want to disable only one single User's ability to use this feature, use commands.deny like so, but replace USERNAME
with the actual username to be denied access to CMD_MODSECURITY:
echo 'CMD_MODSECURITY' >> /usr/local/directadmin/data/users/USERNAME/commands.deny
Customizing ModSecurity Rules
A User or Admin can fully disable ModSecurity rules as needed via SecRuleRemoveById.
Syntax rules for SecRuleRemoveById include:
- must be a positive integer
1234
- ranges are allowed, as long as they're "quoted", eg:
"1234-1239"
The following describes how to use this with DirectAdmin.
Globally - The Old Method
To customize ModSecurity Rules globally, you can add custom rules to /usr/local/directadmin/custombuild/custom/modsecurity/conf/
, and they'll be added automatically to /etc/modsecurity.d
after ./build modsecurity
or ./build modsecurity_rules
is ran. This method still works in addition to the new method.
An example for "MYCUSTOMRULES":
cd /usr/local/directadmin/custombuild
mkdir -p custom/modsecurity/conf
nano -w /usr/local/directadmin/custombuild/custom/modsecurity/conf/MYCUSTOMRULES.conf
./build modsecurity_rules
Building the custom rules with CustomBuild will result in a copy of them being placed in /etc/modsecurity.d/
, which is included in the webserver configs via a series of Includes dependent on the type of webserver you use.
Globally - The New Method
Log into DirectAdmin and use the global ModSecurity interface located at Server Manager >> ModSecurity (https://hostname:2222/admin/modsecurity) to manage the status of ModSecurity, customize rules, and view logs.
Adding rule IDs in this interface will add them to the following global file:
/usr/local/directadmin/data/admin/modsecurity_rules
This file is included by directly by the webserver configs.
Per domain
You can modify the per domain ModSecurity rules either via CustomBuild as described above, or as the Admin or User as described below.
As Admin
Log into DirectAdmin and use the global ModSecurity interface located at Server Manager >> ModSecurity (https://hostname:2222/admin/modsecurity)
If an Admin is making a call to CMD_MODSECURITY, they are allowed to either pass the domain of some other User, or no domain at all. Admin can view rules and logs as well as manage rules for a User via CMD_MODSECURITY
by passing the domain=DOMAIN
parameter. Without this, the global rules will be returned.
As the User
Log into DirectAdmin and use the User ModSecurity interface located at Advanced Features >> ModSecurity (https://hostname:2222/user/modsecurity)
The rules will be stored in the following files:
- for domains:
/usr/local/directadmin/data/users/USER/domains/DOMAIN.COM.modsecurity_rules
- for subdomains:
/usr/local/directadmin/data/users/USER/domains/DOMAIN.COM.subdomains_modsecurity_rules/SUB.modsecurity_rules
Based off of the following template:
/usr/local/directadmin/data/templates/mod_security_rules.conf
Customizing the ModSecurity Configuration
Methods exist in CustomBuild to permit one to customize the ModSecurity configuration as described below. We will use a common example requiring ModSecurity config changes.
Request body no files data length is larger than the configured limit
If you see the following error in the Apache error log, you can increase the limit via the Apache configuration, however, you must do so in a manner that will allow CustomBuild to preserve the change:
ModSecurity: Request body no files data length is larger than the configured limit (131072).
This limit (SecRequestBodyNoFilesLimit) is set via the following files:
/usr/local/directadmin/custombuild/configure/ap2/conf/extra/httpd-modsecurity.conf
/usr/local/directadmin/custombuild/configure/openlitespeed/conf/httpd-modsecurity.conf
/usr/local/directadmin/custombuild/configure/nginx_reverse/conf/nginx-modsecurity.conf
/usr/local/directadmin/custombuild/configure/nginx/conf/nginx-modsecurity.conf
Steps for adjusting this value so that it is not overwritten with the next CustomBuild rebuild of your webserver configuration are defined below. Alternatively, you might try specifying a new setting via the /etc/httpd/conf/extra/httpd-includes.conf
file (or the includes file for your chosen webserver) since it is not touched by CustomBuild.
Apache
- Make sure the custom Apache directory exists:
mkdir -p /usr/local/directadmin/custombuild/custom/ap2/conf/extra
cp -a /usr/local/directadmin/custombuild/configure/ap2/conf/extra/httpd-modsecurity.conf /usr/local/directadmin/custombuild/custom/ap2/conf/extra/httpd-modsecurity.conf
- Edit the value in the custom file as desired:
nano /usr/local/directadmin/custombuild/custom/ap2/conf/extra/httpd-modsecurity.conf
or
vim /usr/local/directadmin/custombuild/custom/ap2/conf/extra/httpd-modsecurity.conf
or use whatever your preferred editor happens to be.
- Rebuild the configuration:
/usr/local/directadmin/custombuild/build rewrite_confs
--
The process is quite similar for other webservers.
OpenLiteSpeed
mkdir -p /usr/local/directadmin/custombuild/custom/openlitespeed/conf/
cp -a /usr/local/directadmin/custombuild/configure/openlitespeed/conf/httpd-modsecurity.conf /usr/local/directadmin/custombuild/custom/openlitespeed/conf/httpd-modsecurity.conf
nano /usr/local/directadmin/custombuild/custom/openlitespeed/conf/httpd-modsecurity.conf
/usr/local/directadmin/custombuild/build rewrite_confs
Nginx Reverse Proxy
mkdir -p /usr/local/directadmin/custombuild/custom/nginx_reverse/conf/
cp -a /usr/local/directadmin/custombuild/configure/nginx_reverse/conf/nginx-modsecurity.conf /usr/local/directadmin/custombuild/custom/nginx_reverse/conf/nginx-modsecurity.conf
nano /usr/local/directadmin/custombuild/custom/nginx_reverse/conf/nginx-modsecurity.conf
/usr/local/directadmin/custombuild/build rewrite_confs
Nginx
mkdir -p /usr/local/directadmin/custombuild/custom/nginx/conf/
cp -a /usr/local/directadmin/custombuild/configure/nginx/conf/nginx-modsecurity.conf /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf
nano /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf
/usr/local/directadmin/custombuild/build rewrite_confs
Enabling ModSecurity Uploadscan
This feature requires ClamAV, so ensure this is enabled first or at least set to 'yes' in the CustomBuild options.conf. Then, run the following CustomBuild commands:
cd /usr/local/directadmin/custombuild
./build set modsecurity_uploadscan yes
./build modsecurity
./build rewrite_confs
How can I confirm that ModSecurity is working
Testing browser-based requests to the site
Just load your domain like so in the browser:
yourdomain.com/?page=../../etc/passwd
And then check the domain's error logs. This should trigger File Inclusion protections in ModSecurity and result in an error. You should see something like this logged:
ModSecurity: Access denied with code 406 (phase 2). Matched "Operator `Rx' with parameter `(?i)(?:\x5c|(?:%(?:c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|2(?:5(?:c(?:0%25af|1%259c)|2f|5c)|%46|f)|(?:(?:f(?:8%8)?0%8|e)0%80%a|bg%q)f|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|u(?:221[56]|002f|EFC8|F025)|1u|5 (400 characters omitted)' against variable `ARGS:page' (Value: `../../etc/passwd' ) [file "/etc/modsecurity.d/REQUEST-930-APPLICATION-ATTACK-LFI.conf"] [line "29"] [id "930100"] [rev ""] [msg "Path Traversal Attack (/../)"] [data "Matched Data: /../ found within ARGS:page: ../../etc/passwd"] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-lfi"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/255/153/126"] [hostname "108.160.151.160"] [uri "/"] [unique_id "161575949767.714205"] [ref "o9,4v4,23o2,4v11,16"], client: X.X.X.X, server: yourdomain.com, request: "GET /?page=../../etc/passwd HTTP/1.1", host: "yourdomain.com"
Error logs are located here, depending on webserver and domain, respectively:
/var/log/*/domains/*.error.log
Testing ModSecurity Uploadscan
If you need to test ModSecurity Uploadscan, you can try uploading the EICAR test files located at the following links to ensure that the upload is blocked:
http://www.eicar.org/anti_virus_test_file.htm
CMD_MODSECURITY
This section describes the CMD_MODSECURITY
command and required/optional GET/POST parameters.
VIEW RULES
Viewing global rules as admin
CMD_MODSECURITY
Viewing a User's per-domain rules
CMD_MODSECURITY?domain=domain.com
Viewing a User's per-subdomain rules
CMD_MODSECURITY?domain=domain.com&subdomain=sub
Viewing json output
The following:
CMD_MODSECURITY?domain=domain.com&json=yes
returns 2 arrays, one for On/Off flags, and the other for skip IDs, eg:
{
"SecRuleRemoveById" :
[
"1234"
],
"flags":
{
"SecFilterScanPOST": "On",
"SecRuleEngine": "On"
}
}
Viewing the options.conf Modsecurity setting value
You can learn if modsecurity=yes
is set in the options.conf via:
CMD_ADDITIONAL_DOMAINS?action=view&domain=domain.com.com&json=yes
with the added value:
modsecurity=yes|no
When called by an Admin, absence of the domain will return the global modsecurity_rules file.
You'll also get a "subdomain_select" array, which is a standard select-box for the available subdomains.
Save flags
- action: CMD_MODSECURITY
- method: POST
- domain=domain.com
- action=save
- SecFilterScanPOST=On|Off
- SecRuleEngine=On|Off
- optional, can also include to save a call if saving and skipping in 1 request:
SecRuleRemoveById=<ID>
When called by an Admin, absence of the domain will save to the global modsecurity_rules
file. This also applies to the rule skips below.
Add rule skip
action: CMD_MODSECURITY
method: POST
domain=domain.com
action=add
SecRuleRemoveById=<ID>
Remove rule skip
action: CMD_MODSECURITY
method: POST
domain=domain.com
action=select
SecRuleRemoveById=<ID>
AND/ORselect0=<ID>
(select1)=<ID>
View logs
JSON output is only of the modsec_audit.log
. This requires the modsec_audit.log
to use the new one-json-per-line format.
Users/Admins
CMD_MODSECURITY?action=log&domain=domain.com
Only show entries matching this domain.
For Users, the domain must be in the domains.list.
For Admins, can be any host value they want.
Sub-domains will be included in the output.
Blank hosts are not included.
Admins
CMD_MODSECURITY?action=log
Shows entries with any Host value (or no Host).
To reduce the log output, you should include the following, specifying your desired value:
&lines=1000
DA starts from the end of the log, parsing lines backwards.
It stops after this number of ENTRIES has been added to the log (was a tail, but it's now entries).
There is also an internal max_time=15 (which is dynamic, timeout / 4, assuming timeout=60).
You can pass &max_time=5
or any other number of seconds, to have the parser stop after this number of seconds, that is if you wish to speed up the display at the cost of losing some older entries.
For very large logs, there is no point in parsing the entire thing if a timeout will happen.
The logs will be output in a "logs" array, filled with a list of transaction arrays.
The top-level json also includes a "summary" array, giving info on how the parser actually went, eg:
"summary":
{
"max_time": "15",
"requested_lines": "500",
"returned_lines": "375",
"time_abort": "yes"
}
If you see "time_abort" ; "yes"
, it would mean that time ran out before actually finding that number of lines/entries.
ModSecurity Templates and Skins
TEMPLATE
/usr/local/directadmin/data/templates/mod_security_rules.conf
Where flags are stored into |FLAGS|
and the multi-line SecRuleRemoveById values are saved into |DISABLEDRULES|
There template starts with |CUSTOM1|
and ends with |CUSTOM2|
, but these tokens are currently blank for possible future expansion.
In the virtual_host2*.conf
, we've added a new token:
|MOD_SECURITY_RULES|
within the <Directory>
context.
Also, this token is available in the nginx_server*.conf
and the openlitespeed_vhost.conf
.
SKINS
New file:
/usr/local/directadmin/data/skins/enhanced/user/mod_security.html
Modified:
/usr/local/directadmin/data/skins/enhanced/user/modify_domain.html
to include a button when:
|*if HAS_MOD_SECURITY="yes"|
pointing to:
/CMD_MODSECURITY?domain=|domain|