writing modsecurity rules

ModSecurity Rule Writing

The ModSecurity Reference Manual should be consulted in any cases where questions arise relating to the syntax of commands:

Rule Syntax

Here basic about SecRule:



  • 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.


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.


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).

Writing ModSecurity Rules

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'"


  • 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.


"@contains () {"
  • “@contains () {“ – Checks the REQUEST_LINE|REQUEST_HEADERS|REQUEST_HEADERS_NAMES variables for the string “() {” and returns true if found.


"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).

ModSecurity Phase

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: () {"

Curl get Response:

<title>500 Internal Server Error</title>
<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 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>
<address>Apache Server at Port 443</address>

Look working Ok, so look apache error log:

[Sun Sep 25 18:42:50.071651 2016] [:error] [pid 3475] [client] 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 ""] [uri "/"] [unique_id "V@fwen8AAQEAAA2TDbQAAAAK"]

And audit log that same:

[25/Sep/2016:18:42:50 +0300] V@fwen8AAQEAAA2TDbQAAAAK 35965 443
GET / HTTP/1.1
Accept: */*
User-Agent: () {

HTTP/1.1 500 Internal Server Error
Content-Length: 613
Connection: close
Content-Type: text/html; charset=iso-8859-1


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 (
Server: Apache
Engine-Mode: "ENABLED"


Rules look working ok, what we expect!

, , ,

Comments are closed.