In this article, we will go over the basics of ModSecurity rule writing and also provide ModSecurity rule examples. In case you are new to ModSecurity, we also have an informative article: What is ModSecurity and why do we need it?
ModSecurity Rule Writing
The ModSecurity Reference Manual should be consulted in any cases where questions arise relating to the syntax of commands: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual
Rule Syntax
Here are basics about SecRule:
SecRule VARIABLES OPERATOR [ACTIONS]
VARIABLES
- ARGS is a collection so it means all arguments including the POST Payload.
- ARGS_GET contains only query string parameters.
- ARGS_POST contains arguments from the POST body.
- FILES Contains a collection of original file names. Available only on inspected multipart/form-data requests.
- FULL_REQUEST Contains the complete request: Request line, Request headers and Request body.
- QUERY_STRING Contains the query string part of a request URI. The value in QUERY_STRING is always provided raw, without URL decoding taking place.
- REQUEST_BODY Holds the raw request body. This variable is available only if the URLENCODED request body processor was used, which will occur by default when the application/x-www-form-urlencoded content type is detected, or if the use of the URLENCODED request body parser was forced.
- REQUEST_HEADERS This variable can be used as either a collection of all of the request headers or can be used to inspect selected headers.
- REQUEST_METHOD This variable holds the request method used in the transaction.
- REQUEST_URI This variable holds the full request URL including the query string data (e.g., /index.php? p=X).
More variables, read manual.
OPERATORS
This specifies a regular expression, pattern or keyword to be checked in the variable(s). Operators begin with the @ character. The full list of operators is available here.
ACTIONS
This specifies what to do if the rule matches. Each action belongs to one of five groups:
- Disruptive used to allow ModSecurity to take an action, for example allow or block
- Non-disruptive action Do something, but that something does not and cannot affect the rule processing flow. Setting a variable, or changing its value is an example of a non-disruptive action. Non-disruptive action can appear in any rule, including each rule belonging to a chain.
- Flow These actions affect the rule flow (for example skip or skipAfter).
- Meta-data Meta-data actions are used to provide more information about rules. Examples include id, rev, severity and msg.
- Data Not really actions, these are mere containers that hold data used by other actions. For example, the status action holds the status that will be used for blocking (if it takes place).
ModSecurity Rule Example
We using our example rule, that block Bash ENV Variable Injection Attack.
Example rule
SecRule REQUEST_LINE|REQUEST_HEADERS|REQUEST_HEADERS_NAMES "@contains () {" "id:420008,phase:2,t:none,t:lowercase,deny,status:500,log,msg:'Malware expert - user-agent: Bash ENV Variable Injection Attack'"
VARIABLES
REQUEST_LINE|REQUEST_HEADERS|REQUEST_HEADERS_NAMES
- REQUEST_LINE – This variable holds the complete request line sent to the server (including the request method and HTTP version information).
- REQUEST_HEADERS – All of the request headers.
- REQUEST_HEADERS_NAMES – All of the names of the request headers.
OPERATOR
"@contains () {"
- “@contains () {“ – Checks the REQUEST_LINE|REQUEST_HEADERS|REQUEST_HEADERS_NAMES variables for the string “() {” and returns true if found.
ACTIONS
"id:420008,phase:2,t:none,t:lowercase,deny,status:500,log,msg:'Malware expert - user-agent: Bash ENV Variable Injection Attack'"
id:’420008′ – The unique id that is assigned to this rule (or chain) in which it appears.
phase:2 – Places the rule (or chain) in Phase 2 processing. There are 5 phases including Request Headers (1), Request Body (2), Response Headers (3), Response Body (4) and Logging (5).
t:none – Indicates that no action is used to transform the value of the variable used in the rule before matching.
t:lowercase – Converts REQUEST to lowercase.
deny – Deny process request to client.
status:500 – Apache header status to client.
log – Rule matches appear in both the error and audit logs.
msg:’Malware expert – user-agent: Bash ENV Variable Injection Attack’ – The custom message assigned to the rule (or chain) in which it appears.
Testing Rule
Now start testing that rule, so we use curl to get request to server:
# curl -H "User-Agent: () {" https://malware.expert
Curl get Response:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>500 Internal Server Error</title> </head><body> <h1>Internal Server Error</h1> <p>The server encountered an internal error or misconfiguration and was unable to complete your request.</p> <p>Please contact the server administrator at webmaster@malware.expert to inform them of the time this error occurred, and the actions you performed just before this error.</p> <p>More information about this error may be available in the server error log.</p> <hr> <address>Apache Server at malware.expert Port 443</address> </body></html>
Look working Ok, so look apache error log:
[Sun Sep 25 18:42:50.071651 2016] [:error] [pid 3475] [client 127.0.0.1] ModSecurity: Access denied with code 500 (phase 2). String match "() {" at REQUEST_HEADERS:User-Agent. [file "/etc/modsecurity/malware_expert.conf"] [line "97"] [id "420008"] [msg "Malware expert - user-agent: Bash ENV Variable Injection Attack"] [hostname "malware.expert"] [uri "/"] [unique_id "V@fwen8AAQEAAA2TDbQAAAAK"]
And audit log that same:
--f9adec1d-A-- [25/Sep/2016:18:42:50 +0300] V@fwen8AAQEAAA2TDbQAAAAK 127.0.0.1 35965 127.0.0.1 443 --f9adec1d-B-- GET / HTTP/1.1 Host: malware.expert Accept: */* User-Agent: () { --f9adec1d-F-- HTTP/1.1 500 Internal Server Error Content-Length: 613 Connection: close Content-Type: text/html; charset=iso-8859-1 --f9adec1d-E-- --f9adec1d-H-- Message: Access denied with code 500 (phase 2). String match "() {" at REQUEST_HEADERS:User-Agent. [file "/etc/modsecurity/malware_expert.conf"] [line "97"] [id "420008"] [msg "Malware expert - user-agent: Bash ENV Variable Injection Attack"] Action: Intercepted (phase 2) Stopwatch: 1474818170070960 1010 (- - -) Stopwatch2: 1474818170070960 1010; combined=177, p1=25, p2=147, p3=0, p4=0, p5=5, sr=55, sw=0, l=0, gc=0 Response-Body-Transformed: Dechunked Producer: ModSecurity for Apache/2.9.0 (http://www.modsecurity.org/). Server: Apache Engine-Mode: "ENABLED" --f9adec1d-Z--
Rules look working ok, what we expect!
Conclusion
Hope this tutorial will help you writing own Modsecurity rules and protect your applications.
Malware.Expert is also providing ModSecurity Rules which have advanced protection against malware attacks in WebHosting.
For more server security tips and tricks, click on subscribe.