ModSecurity is a popular open source tool originally designed as a module for Apache HTTP server for securing web applications. It is a web application firewall (WAF) mainly used for real-time web application monitoring, logging, and access control.
There are two main aspects of ModSecurity which can be leveraged very effectively within Access Gateway. First, at its core, ModSecurity allows the admin to access HTTP stream in real-time, along with the ability to parse it. This is essential for real-time security monitoring. The second aspect is it allows continuous security assessment of both behaviors of the external parties, as well as the behavior of the system itself in the background. It’s sort of the first line of defense that can detect traces of many abnormalities and security weaknesses before they are exploited.
In this article, ModSecurity is being deployed as Apache module and therefore embedded to Access Gateway. So Access Gateway’s resources are shared by ModSecurity. More details are in a later part of this article.
This article covers the following items in detail:
ModSecurity is an engine which requires rules. Rules make it an extremely powerful and versatile engine to control HTTP request & response down to byte level. To utilize its power, ModSecurity provides a platform, a rule configuration language, known as 'SecRules' for real-time monitoring, logging, and filtering of HTTP communications based on rules.
ModSecurity is most commonly deployed to provide protection against generic classes of vulnerabilities using the Open Web Application Security Project (OWASP) Core Rule Set (CRS). This is an open-source set of rules written in ModSecurity's SecRules language. CRS aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts. The Core Rule Set provides protection against many common attack categories, including:
The ModSecurity tarball has ModSecurity Apache module Ver 2.9.2 and OWASP’s Core Rule Set Ver 3.0.2.
Please follow the steps mentioned below to enable the ModSecurity module with CRS:
# cp ModSecurity.tar.gz /etc/opt/novell/apache2/conf/
# cd /etc/opt/novell/apache2/conf/
# tar -zxvf ModSecurity.tar.gz
# cp -r ModSecurity/modsec.d /etc/opt/novell/apache2/conf/
# cp -r ModSecurity/owasp-modsecurity-crs-3.0.2 /etc/opt/novell/apache2/conf/
# ln -s owasp-modsecurity-crs-3.0.2 crs
# rm -r ModSecurity ModSecurity.tar.gz
For NAM 4.4.3
#cp ModSecurity/4.4.3/mod_security2.so /opt/novell/apache2/libexec/
For NAM 4.4.2
#cp ModSecurity/4.4.2/mod_security2.so /opt/novell/apache2/libexec/
Add the following line at the beginning of the LoadModule section of the httpd.conf file.
LoadModule security2_module libexec/mod_security2.so
Uncomment the following line available in the same section.
LoadModule unique_id_module libexec/mod_unique_id.so
There are a few configuration/directives which are critical for ModSecurity and CRS to work together as expected without giving any unwanted surprises.
The following section covers a few settings and its usage with a detailed description. README and conf files of both ModSecurity and CRS can also be used for reference.
There is always some risks and impact when ModSecurity is enabled on a production environment. There are chances of false positive, blocking a legitimate user from accessing resources, performance degradation, etc. Chances are high when ModSecurity is deployed as Disruptive mode.
Following are a few generic and recommended settings which make ModSecurity less offensive and never blocks any request.
It's verbose only mode where separate logs are created for any security threat detected.
There are few more settings to gauge the impact on performance and other server resources.
The configuration files (crs-setup.conf and modsecurity-base.conf are available inside path/etc/opt/novell/apache2/conf/ ) which are copied during installation steps mentioned above already have the following settings enabled.
Setting ModSecurity rule engine to process rules but never to execute any disruptive actions (block, deny, drop, allow, proxy and redirect) is done by:
Note: The Admin can set it to On and play with additional settings like anomaly threshold, sampling percentage, etc., after the initial round of testing and performance impact analysis.
The logs generated by ModSecurity are dumped to a new file using:
The verboseness of the debug log data is set as below
Messages at levels 1-3 are always copied to the Apache error log. Therefore, admin can use level 0 as default logging level in production performance is very critical. Having said that, the best value to use is 3, since being ModSecurity at verbose mode, analyzing warnings & errors related to ModSecurity will be easier.
CRS with Anomaly Scoring Mode is the default and recommended mode since it gives the most accurate log information and offers the most flexibility in setting blocking policies. In this mode, each matching rule increases an 'anomaly score'. Each rule in the CRS has an associated severity level. These are the default scoring points for each severity level. These settings will be used to increment the anomaly score if a rule matches. These scores are cumulative. So it's possible for a request to hit multiple rules.
In Anomaly Mode, there is also a Blocking Threshold Levels. This is the level upon reaching an inbound request or outbound response gets blocked. Blocking evaluation rules apply a disruptive action, ideally returning an error 403. It is a common practice to start a new CRS installation with elevated anomaly scoring thresholds (>100) and then lowers the limits as your confidence in the setup grows.
Current Anomaly Mode Blocking Threshold Levels for inbound request is set to 500 since the idea is not to block the request during the testing phase. In case a request is reaching 500, something really bad with the request or configuration error. Here are the current settings:
SecAction "id:900100, phase:1, nolog, pass, t:none, setvar:tx.critical_anomaly_score=5, \ setvar:tx.error_anomaly_score=4, setvar:tx.warning_anomaly_score=3, \ setvar:tx.notice_anomaly_score=2"
SecAction "id:900110, phase:1, nolog, pass, t:none, setvar:tx.inbound_anomaly_score_threshold=500, \ setvar:tx.outbound_anomaly_score_threshold=500"
Note: Anomaly setting with disruptive action is effective only when SecRuleEngine setting is set to On
The Paranoia Level (PL) setting allows admin to choose the desired level of rule checks. With each paranoia level increase, the CRS enables additional rules giving you a higher level of security. However, higher paranoia levels also increase the possibility of blocking some legitimate traffic due to false alarms (false positive). A paranoia level of 1 is the default. In this level, most core rules are enabled. PL1 is advised for beginners, installations covering many different sites and applications, and for setups with standard security requirements. At PL1 false alarms are very rare. Here is the default setting
SecAction "id:900000, phase:1, nolog, pass, t:none, setvar:tx.paranoia_level=1"
Adding the Core Rule Set to an existing production site can lead to false positives, unexpected performance issues, and other undesired side effects. It can be beneficial to test the water first by enabling the CRS for a limited number of requests only and then, with growing confidence after fixing issues, raise the ratio of requests being sent into the ruleset. Adjust the percentage of requests that are funneled into the Core Rules by setting as below.
SecAction "id:900400, phase:1, pass, nolog, setvar:tx.sampling_percentage=25"
So with this only a quarter of total traffic will go through CRS.
Allowed HTTP methods
Currently, almost all HTTP methods are allowed as below.
SecAction "id:900200, phase:1, nolog, pass, t:none, setvar:'tx.allowed_methods=GET HEAD POST OPTIONS PUT PATCH DELETE CHECKOUT COPY DELETE LOCK MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK'"
This can be modified depending on the application AG is protecting.
By default, the following content types are allowed in requests.
application/x-www-form-urlencoded, multipart/form-data, text/xml, application/xml, application/soap xml, application/x-amf, application/json, application/octet-stream, text/plain, text/x-gwt-rpc
Here is the current setting.
SecAction "id:900220, phase:1, nolog, pass, t:none,\ setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/soap xml|application/x-amf|application/json|application/octet-stream|text/plain|text/x-gwt-rpc'"
Allowed HTTP versions are HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0
SecAction "id:900230, phase:1, nolog, pass, t:none, setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'"
Forbidden file extensions
In a bid to Guards against unintended exposure of development/configuration files access to following extensions are restricted.
SecAction "id:900240, phase:1, nolog, pass, t:none, setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'"
File system configuration
ModSecurity is required to store temporary files and some persistent data under the local file system. The current setting is set to /tmp using the following directive. However, /tmp is less than ideal and it is recommended to specify a location that's private.
Following are a few samples of logs generated when any threat is detected by ModSecurity using CRS:
[himmagapp.novell.com/sid#562e6c2e9140][rid#7fae48014ef0][/bajesh/HIMDEEP/modsec/aaa.html] Warning. detected XSS using libinjection. [file "/etc/opt/novell/apache2/conf/crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "64"] [id "941100"] [rev "2"] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: via found within ARGS_NAMES:<SCRIPT>alert(\x5cxe2\x5cx80\x5cx9cCookie\x5cxe2\x5cx80\x5cx9d document.cookie)</SCRIPT>: <SCRIPT>alert(\x22Cookie\x22 document.cookie)</SCRIPT>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "9"] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag]
[himmagapp.novell.com/sid#562e6c2e9140][rid#7fae48014ef0][/bajesh/HIMDEEP/modsec/aaa.html] Warning. Matched phrase "document.cookie" at ARGS_NAMES:<SCRIPT>alert(\xe2\x80\x9cCookie\xe2\x80\x9d document.cookie)</SCRIPT>. [file "/etc/opt/novell/apache2/conf/crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "303"] [id "941180"] [rev "2"] [msg "Node-Validator Blacklist Keywords"] [data "Matched Data: document.cookie found within ARGS_NAMES:<SCRIPT>alert(\x5cxe2\x5cx80\x5cx9cCookie\x5cxe2\x5cx80\x5cx9d document.cookie)</SCRIPT>: <script>alert(\x22cookie\x22 document.cookie)</script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "8"] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag]
[himmagapp.novell.com/sid#562e6c2e9140][rid#7fae48014ef0][/bajesh/HIMDEEP/modsec/aaa.html] Warning. Matched phrase "bin/bash" at ARGS:exec. [file "/etc/opt/novell/apache2/conf/crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "448"] [id "932160"] [rev "1"] [msg "Remote Command Execution: Unix Shell Code Found"] [data "Matched Data: bin/bash found within ARGS:exec: /bin/bash"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "8"] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag]
[himmagapp.novell.com/sid#562e6c2e9140][rid#7fae4401f9c0][/bajesh/HIMDEEP/modsec/aaa.html] Access denied with code 400 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file "/etc/opt/novell/apache2/conf/crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "57"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [severity "CRITICAL"] [tag] [tag] [tag] [tag] [tag]
[himmagapp.novell.com/sid#562e6c2e9140][rid#7fae48004980][/bajesh/HIMDEEP/modsec/testpost.php] Warning. detected SQLi using libinjection with fingerprint 's&sos' [file "/etc/opt/novell/apache2/conf/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "68"] [id "942100"] [rev "1"] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: s&sos found within ARGS:username: 1' or '1' = '1"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "8"] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag] [tag]
As it is seen above, when ModSecurity detects any threat using CRS, messages with various information get appended to the log file set by SecDebugLog directive.
Analyzing these logs and searching for a specific string can let the admin know various attacks and severity levels that the server has gone through. As the first step, the following are the list of strings that can be looked for in debug log file:
Enabling ModSecurity definitely impacts on following areas of Access Gateway:
The Admin can play around with the available directives and settings (sampling, anomaly threshold scor,e etc.) mentioned above and gauge the impact of ModSecurity on Access Gateway performance. A major impact is on Memory usage so increasing size of RAM is recommended. As CRS has around 200 rules, there will be a reduction in the number of simultaneous connections that Access Gateway can successfully handle if the available memory is not sufficient. Impact on CPU is between (1% - 5%).