Each action belongs to one of five groups:
Cause ModSecurity to do something. In many cases something means block transaction, but not in all. For example, the allow action is classified as a disruptive action, but it does the opposite of blocking. There can only be one disruptive action per rule (if there are multiple disruptive actions present, or inherited, only the last one will take effect), or rule chain (in a chain, a disruptive action can only appear in the first rule).
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.
These actions affect the rule flow (for example
skip
or skipAfter
).
Meta-data actions are used to provide more information about
rules. Examples include id
,
rev
, severity
and
msg
.
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).
Description: Stops rule processing on a successful match and allows the transaction to proceed.
Action Group: Disruptive
Example:
SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,allow
Prior to ModSecurity 2.5 the allow
action would
only affect the current phase. An allow
in phase 1
would skip processing the remaining rules in phase 1 but the rules from
phase 2 would execute. Starting with v2.5.0 allow
was
enhanced to allow for fine-grained control of what is done. The
following rules now apply:
If used one its own, like in the example above,
allow
will affect the entire transaction,
stopping processing of the current phase but also skipping over all
other phases apart from the logging phase. (The logging phase is
special; it is designed to always execute.)
If used with parameter "phase", allow
will
cause the engine to stop processing the current phase. Other phases
will continue as normal.
If used with parameter "request", allow
will cause the engine to stop processing the current phase. The next
phase to be processed will be phase
RESPONSE_HEADERS
.
Examples:
# Do not process request but process response. SecAction phase:1,allow:request # Do not process transaction (request and response). SecAction phase:1,allow
If you want to allow a response through, put a rule in phase
RESPONSE_HEADERS
and simply use
allow
on its own:
# Allow response through. SecAction phase:3,allow
Description: Appends text given as parameter
to the end of response body. For this action to work content injection
must be enabled by setting SecContentInjection
to
On
. Also make sure you check the content type of the
response before you make changes to it (e.g. you don't want to inject
stuff into images).
Action Group: Non-disruptive
Processing Phases: 3 and 4.
Example:
SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,pass,append:'<hr>Footer'"
Description: Marks the transaction for logging in the audit log.
Action Group: Non-disruptive
Example:
SecRule REMOTE_ADDR "^192\.168\.1\.100$" auditlog,phase:1,allow
Note
The auditlog action is now explicit if log is already specified.
Description: Performs the default disruptive action.
Action Group: Disruptive
It is intended to be used by ruleset writers to signify that the
rule was intended to block and leaves the "how" up to the administrator.
This action is currently a placeholder which will just be replaced by
the action from the last SecDefaultAction
in the same
context. Using the block
action with the
SecRuleUpdateActionById
directive allows a rule to be
reverted back to the previous SecDefaultAction
disruptive action.
In future versions of ModSecurity, more control and functionality will be added to define "how" to block.
Examples:
In the following example, the second rule will "deny" because of the SecDefaultAction disruptive action. The intent being that the administrator could easily change this to another disruptive action without editing the actual rules.
### Administrator defines "how" to block (deny,status:403)... SecDefaultAction phase:2,deny,status:403,log,auditlog ### Included from a rulest... # Intent is to warn for this User Agent SecRule REQUEST_HEADERS:User-Agent "perl" "phase:2,pass,msg:'Perl based user agent identified'" # Intent is to block for this User Agent, "how" described in SecDefaultAction SecRule REQUEST_HEADERS:User-Agent "nikto" "phase:2,block,msg:'Nikto Scanners Identified'"
In the following example, The rule is reverted back to the
pass
action defined in the SecDefaultAction directive
by using the SecRuleUpdateActionById
directive in
conjuction with the block
action. This allows an
administrator to override an action in a 3rd party rule without
modifying the rule itself.
### Administrator defines "how" to block (deny,status:403)... SecDefaultAction phase:2,pass,log,auditlog ### Included from a rulest... SecRule REQUEST_HEADERS:User-Agent "nikto" "id:1,phase:2,deny,msg:'Nikto Scanners Identified'" ### Added by the administrator SecRuleUpdateActionById 1 "block"
Description: When used together with the regular expression operator, capture action will create copies of regular expression captures and place them into the transaction variable collection. Up to ten captures will be copied on a successful pattern match, each with a name consisting of a digit from 0 to 9.
Action Group: Non-disruptive
Example:
SecRule REQUEST_BODY "^username=(\w{25,})" phase:2,capture,t:none,chain
SecRule TX:1 "(?:(?:a(dmin|nonymous)))"
Note
The 0 data captures the entire REGEX match and 1 captures the data in the first parens, etc...
Description: Chains the rule where the action is placed with the rule that immediately follows it. The result is called a rule chain. Chained rules allow for more complex rule matches where you want to use a number of different VARIABLES to create a better rule and to help prevent false positives.
Action Group: Flow
Example:
# Refuse to accept POST requests that do
# not specify request body length. Do note that
# this rule should be preceeded by a rule that verifies
# only valid request methods (e.g. GET, HEAD and POST) are used.
SecRule REQUEST_METHOD ^POST$ chain,t:none
SecRule REQUEST_HEADER:Content-Length ^$ t:none
In programming language concepts, think of chained rules somewhat similar to AND conditional statements. The actions specified in the first portion of the chained rule will only be triggered if all of the variable checks return positive hits. If one aspect of the chained rule is negative, then the entire rule chain is negative. Also note that disruptive actions, execution phases, metadata actions (id, rev, msg), skip and skipAfter actions can only be specified on by the chain starter rule.
Description: The ctl action allows configuration options to be updated for the transaction.
Action Group: Non-disruptive
Example:
# Parse requests with Content-Type "text/xml" as XML
SecRule REQUEST_CONTENT_TYPE ^text/xml nolog,pass,ctl:requestBodyProcessor=XML
Note
The following configuration options are supported:
auditEngine
auditLogParts
debugLogLevel
ruleRemoveById
(single rule
ID, or a single rule ID range accepted as parameter)
requestBodyAccess
forceRequestBodyVariable
requestBodyLimit
requestBodyProcessor
responseBodyAccess
responseBodyLimit
ruleEngine
With the exception of
requestBodyProcessor
and
forceRequestBodyVariable
, each configuration option
corresponds to one configuration directive and the usage is
identical.
The requestBodyProcessor
option allows you to
configure the request body processor. By default ModSecurity will use
the URLENCODED
and MULTIPART
processors to process an application/x-www-form-urlencoded
and a
multipart/form-data
bodies,
respectively. A third processor, XML
, is also
supported, but it is never used implicitly. Instead you must tell
ModSecurity to use it by placing a few rules in the REQUEST_HEADERS
processing phase. After the
request body was processed as XML you will be able to use the
XML-related features to inspect it.
Request body processors will not interrupt a transaction if an
error occurs during parsing. Instead they will set variables REQBODY_PROCESSOR_ERROR
and REQBODY_PROCESSOR_ERROR_MSG
. These variables
should be inspected in the REQUEST_BODY
phase and an appropriate action
taken.
The forceRequestBodyVariable
option allows you
to configure the REQUEST_BODY
variable to be set when
there is no request body processor configured. This allows for
inspection of request bodies of unknown types.
Description: Stops rule processing and intercepts transaction.
Action Group: Disruptive
Example:
SecRule REQUEST_HEADERS:User-Agent "nikto" "log,deny,msg:'Nikto Scanners Identified'"
Description: Decrement counter based on its age.
Action Group: Non-Disruptive
Example: The following example will decrement the counter by 60 every 300 seconds.
SecAction deprecatevar:session.score=60/300
Note
Counter values are always positive, meaning the value will never go below zero.
Description: Immediately initiate a "connection close" action to tear down the TCP connection by sending a FIN packet.
Action Group: Disruptive
Example: The following example initiates an IP collection for tracking Basic Authentication attempts. If the client goes over the threshold of more than 25 attempts in 2 minutes, it will DROP subsequent connections.
SecAction initcol:ip=%{REMOTE_ADDR},nolog
SecRule ARGS:login "!^$" \
nolog,phase:1,setvar:ip.auth_attempt=+1,deprecatevar:ip.auth_attempt=20/120
SecRule IP:AUTH_ATTEMPT "@gt 25" \
log,drop,phase:1,msg:'Possible Brute Force Attack"
Note
This action is currently not available on Windows based builds. This action is extremely useful when responding to both Brute Force and Denial of Service attacks in that, in both cases, you want to minimize both the network bandwidth and the data returned to the client. This action causes error message to appear in the log "(9)Bad file descriptor: core_output_filter: writing data to the network"
Description: Executes an external
script/binary supplied as parameter. As of v2.5.0, if the parameter
supplied to exec
is a Lua script (detected by the
.lua
extension) the script will be processed
internally. This means you will get direct access
to the internal request context from the script. Please read the
SecRuleScript
documentation for more details on how
to write Lua scripts.
Action Group: Non-disruptive
Example:
# The following is going to execute /usr/local/apache/bin/test.sh # as a shell script on rule match. SecRule REQUEST_URI "^/cgi-bin/script\.pl" \ "phase:2,t:none,t:lowercase,t:normalisePath,log,exec:/usr/local/apache/bin/test.sh" # The following is going to process /usr/local/apache/conf/exec.lua # internally as a Lua script on rule match. SecRule ARGS:p attack log,exec:/usr/local/apache/conf/exec.lua
The exec action is executed independently from any disruptive actions. External scripts will always be called with no parameters. Some transaction information will be placed in environment variables. All the usual CGI environment variables will be there. You should be aware that forking a threaded process results in all threads being replicated in the new process. Forking can therefore incur larger overhead in multi-threaded operation. The script you execute must write something (anything) to stdout. If it doesn't ModSecurity will assume execution didn't work.
Description: Configures a collection variable to expire after the given time in seconds.
Action Group: Non-disruptive
Example:
SecRule REQUEST_COOKIES:JSESSIONID "!^$" nolog,phase:1,pass,chain
SecAction setsid:%{REQUEST_COOKIES:JSESSIONID}
SecRule REQUEST_URI "^/cgi-bin/script\.pl" \
"phase:2,t:none,t:lowercase,t:normalisePath,log,allow,\
setvar:session.suspicious=1,expirevar:session.suspicious=3600,phase:1"
Note
You should use expirevar actions at the same time that you use setvar actions in order to keep the indented expiration time. If they are used on their own (perhaps in a SecAction directive) the expire time could get re-set. When variables are removed from collections, and there are no other changes, collections are not written to disk at the end of request. This is because the variables can always be expired again when the collection is read again on a subsequent request.
Description: Assigns a unique ID to the rule or chain.
Action Group: Meta-data
Example:
SecRule &REQUEST_HEADERS:Host "@eq 0" \
"log,id:60008,severity:2,msg:'Request Missing a Host Header'"
Note
These are the reserved ranges:
1-99,999; reserved for local (internal) use. Use as you see fit but do not use this range for rules that are distributed to others.
100,000-199,999; reserved for internal use of the engine, to assign to rules that do not have explicit IDs.
200,000-299,999; reserved for rules published at modsecurity.org.
300,000-399,999; reserved for rules published at gotroot.com.
400,000-419,999; unused (available for reservation).
420,000-429,999; reserved for ScallyWhack.
430,000-899,999; unused (available for reservation).
900,000-999,999; reserved for the Core Rules project.
1,000,000 and above; unused (available for reservation).
Description: Initialises a named persistent collection, either by loading data from storage or by creating a new collection in memory.
Action Group: Non-disruptive
Example: The following example initiates IP address tracking.
SecAction initcol:ip=%{REMOTE_ADDR},nolog
Note
Collections are loaded into memory when the initcol action is encountered. The collection in storage will be persisted (and the appropriate counters increased) only if it was changed during transaction processing.
See the "Persistant Storage" section for further details.
Description: Indicates that a successful match of the rule needs to be logged.
Action Group: Non-disruptive
Example:
SecAction initcol:ip=%{REMOTE_ADDR},log
Note
This action will log matches to the Apache error log file and the ModSecurity audit log.
Description: Allows a data fragment to be logged as part of the alert message.
Action Group: Non-disruptive
Example:
SecRule &ARGS:p "@eq 0" "log,logdata:'%{TX.0}'"
Note
The logdata information appears in the error and/or audit log files and is not sent back to the client in response headers. Macro expansion is preformed so you may use variable names such as %{TX.0}, etc. The information is properly escaped for use with logging binary data.
Description: Assigns a custom message to the rule or chain.
Action Group: Meta-data
Example:
SecRule &REQUEST_HEADERS:Host "@eq 0" \ "log,id:60008,severity:2,msg:'Request Missing a Host Header'"
Note
The msg information appears in the error and/or audit log files and is not sent back to the client in response headers.
Description: If enabled ModSecurity will perform multiple operator invocations for every target, before and after every anti-evasion transformation is performed.
Action Group: Non-disruptive
Example:
SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
SecRule ARGS "attack" multiMatch
Note
Normally, variables are evaluated once, only after all transformation functions have completed. With multiMatch, variables are checked against the operator before and after every transformation function that changes the input.
Description: Indicates that a successful match of the rule should not be used as criteria whether the transaction should be logged to the audit log.
Action Group: Non-disruptive
Example:
SecRule REQUEST_HEADERS:User-Agent "Test" allow,noauditlog
Note
If the SecAuditEngine is set to On, all of the transactions will
be logged. If it is set to RelevantOnly, then you can control it with
the noauditlog action. Even if the noauditlog action is applied to a
specific rule and a rule either before or after triggered an audit
event, then the transaction will be logged to the audit log. The correct
way to disable audit logging for the entire transaction is to use
"ctl:auditEngine=Off
"
Description: Prevents rule matches from appearing in both the error and audit logs.
Action Group: Non-disruptive
Example:
SecRule REQUEST_HEADERS:User-Agent "Test" allow,nolog
Note
The nolog action also implies noauditlog.
Description: Continues processing with the next rule in spite of a successful match.
Action Group: Disruptive
Example1:
SecRule REQUEST_HEADERS:User-Agent "Test" log,pass
When using pass with SecRule with multiple targets, all targets will be processed and all non-disruptive actions will trigger for every match found. In the second example the TX:test target would be incremented by 1 for each matching argument.
Example2:
SecRule ARGS "test" log,pass,setvar:TX.test=+1
Note
The transaction will not be interrupted but a log will be generated for each matching target (unless logging has been suppressed).
Description: Pauses transaction processing for the specified number of milliseconds.
Action Group: Non-disruptive
Example:
SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403,pause:5000
Note
This feature can be of limited benefit for slowing down Brute Force Scanners, however use with care. If you are under a Denial of Service type of attack, the pause feature may make matters worse as this feature will cause child processes to sit idle until the pause is completed.
Description: Places the rule (or the rule chain) into one of five available processing phases.
Action Group: Meta-data
Example:
SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403
Note
Keep in mind that is you specify the incorrect phase, the target variable that you specify may be empty. This could lead to a false negative situation where your variable and operator (RegEx) may be correct, but it misses malicious data because you specified the wrong phase.
Description: Prepends text given as parameter
to the response body. For this action to work content injection must be
enabled by setting SecContentInjection
to
On
. Also make sure you check the content type of the
response before you make changes to it (e.g. you don't want to inject
stuff into images).
Action Group: Non-disruptive
Processing Phases: 3 and 4.
Example:
SecRule RESPONSE_CONTENT_TYPE ^text/html "phase:3,nolog,pass,prepend:'Header<br>'"
Description: Intercepts transaction by forwarding request to another web server using the proxy backend.
Action Group: Disruptive
Example:
SecRule REQUEST_HEADERS:User-Agent "Test" log,proxy:http://www.honeypothost.com/
Note
For this action to work, mod_proxy must also be installed. This action is useful if you would like to proxy matching requests onto a honeypot webserver.
Description: Intercepts transaction by issuing a redirect to the given location.
Action Group: Disruptive
Example:
SecRule REQUEST_HEADERS:User-Agent "Test" \
log,redirect:http://www.hostname.com/failed.html
Note
If the status
action is present
and its value is acceptable (301, 302, 303, or 307) it will be used for
the redirection. Otherwise status code 302 will be used.
Description: Specifies rule revision.
Action Group: Meta-data
Example:
SecRule REQUEST_METHOD "^PUT$" "id:340002,rev:1,severity:2,msg:'Restricted HTTP function'"
Note
This action is used in combination with the id
action to allow the same rule ID to be used
after changes take place but to still provide some indication the rule
changed.
Description: Sanitises (replaces each byte with an asterisk) a named request argument prior to audit logging.
Action Group: Non-disruptive
Example:
SecAction nolog,phase:2,sanitiseArg:password
Note
The sanitize actions do not sanitize any data within the actual raw requests but only on the copy of data within memory that is set to log to the audit log. It will not sanitize the data in the modsec_debug.log file (if the log level is set high enough to capture this data).
Description: Sanitises the variable (request argument, request header, or response header) that caused a rule match.
Action Group: Non-disruptive
Example: This action can be used to sanitise arbitrary transaction elements when they match a condition. For example, the example below will sanitise any argument that contains the word password in the name.
SecRule ARGS_NAMES password nolog,pass,sanitiseMatched
Note
Same note as sanitiseArg.
Description: Sanitises a named request header.
Action Group: Non-disruptive
Example: This will sanitise the data in the Authorization header.
SecAction log,phase:1,sanitiseRequestHeader:Authorization
Note
Same note as sanitiseArg.
Description: Sanitises a named response header.
Action Group: Non-disruptive
Example: This will sanitise the Set-Cookie data sent to the client.
SecAction log,phase:3,sanitiseResponseHeader:Set-Cookie
Note
Same note as sanitiseArg.
Description: Assigns severity to the rule it is placed with.
Action Group: Meta-data
Example:
SecRule REQUEST_METHOD "^PUT$" "id:340002,rev:1,severity:CRITICAL,msg:'Restricted HTTP function'"
Note
Severity values in ModSecurity follow those of syslog, as below:
0 - EMERGENCY
1 - ALERT
2 - CRITICAL
3 - ERROR
4 - WARNING
5 - NOTICE
6 - INFO
7 - DEBUG
It is possible to specify severity levels using either the numerical values or the text values. You should always specify severity levels using the text values. The use of the numerical values is deprecated (as of v2.5.0) and may be removed in one of the susequent major updates.
Description: Special-purpose action that
initialises the USER
collection.
Action Group: Non-disruptive
Example:
SecAction setuid:%{REMOTE_USER},nolog
Note
After initialisation takes place the variable USERID
will be available for use in the
subsequent rules.
Description: Special-purpose action that
initialises the SESSION
collection.
Action Group: Non-disruptive
Example:
# Initialise session variables using the session cookie value
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
Note
On first invocation of this action the collection will be empty
(not taking the predefined variables into account - see initcol
for more information). On subsequent
invocations the contents of the collection (session, in this case) will
be retrieved from storage. After initialisation takes place the
variable SESSIONID
will be available
for use in the subsequent rules.This action understands each application
maintains its own set of sessions. It will utilise the current web
application ID to create a session namespace.
Description: Creates, removes, or updates an environment variable.
Action Group: Non-disruptive
Examples:
To create a new variable (if you omit the value 1
will be used):
setenv:name=value
To remove a variable:
setenv:!name
Note
This action can be used to establish communication with other Apache modules.
Description: Creates, removes, or updates a variable in the specified collection.
Action Group: Non-disruptive
Examples:
To create a new variable:
setvar:tx.score=10
To remove a variable prefix the name with exclamation mark:
setvar:!tx.score
To increase or decrease variable value use +
and -
characters in front of a numerical value:
setvar:tx.score=+5
Description: Skips one or more rules (or chains) on successful match.
Action Group: Flow
Example:
SecRule REQUEST_URI "^/$" \
"phase:2,chain,t:none,skip:2"
SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain"
SecRule REQUEST_HEADERS:User-Agent "^Apache \(internal dummy connection\)$" "t:none"
SecRule &REQUEST_HEADERS:Host "@eq 0" \
"deny,log,status:400,id:960008,severity:4,msg:'Request Missing a Host Header'"
SecRule &REQUEST_HEADERS:Accept "@eq 0" \
"log,deny,log,status:400,id:960015,msg:'Request Missing an Accept Header'"
Note
Skip only applies to the current processing phase and not necessarily the order in which the rules appear in the configuration file. If you group rules by processing phases, then skip should work as expected. This action can not be used to skip rules within one chain. Accepts a single parameter denoting the number of rules (or chains) to skip.
Description: Skips rules (or chains) on
successful match resuming rule execution after the specified rule ID or
marker (see SecMarker
) is found.
Action Group: Flow
Example:
SecRule REQUEST_URI "^/$" "chain,t:none,skipAfter:960015"
SecRule REMOTE_ADDR "^127\.0\.0\.1$" "chain"
SecRule REQUEST_HEADERS:User-Agent "^Apache \(internal dummy connection\)$" "t:none"
SecRule &REQUEST_HEADERS:Host "@eq 0" \
"deny,log,status:400,id:960008,severity:4,msg:'Request Missing a Host Header'"
SecRule &REQUEST_HEADERS:Accept "@eq 0" \
"log,deny,log,status:400,id:960015,msg:'Request Missing an Accept Header'"
Note
SkipAfter
only applies to the current
processing phase and not necessarily the order in which the rules appear
in the configuration file. If you group rules by processing phases, then
skip should work as expected. This action can not be used to skip rules
within one chain. Accepts a single parameter denoting the last rule ID
to skip.
Description: Specifies the response status
code to use with actions deny
and redirect
.
Action Group: Data
Example:
SecDefaultAction log,deny,status:403,phase:1
Note
Status actions defined in Apache scope locations (such as Directory, Location, etc...) may be superseded by phase:1 action settings. The Apache ErrorDocument directive will be triggered if present in the configuration. Therefore if you have previously defined a custom error page for a given status then it will be executed and its output presented to the user.
Description: This action can be used which transformation function should be used against the specified variables before they (or the results, rather) are run against the operator specified in the rule.
Action Group: Non-disruptive
Example:
SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
SecRule REQUEST_COOKIES:SESSIONID "47414e81cbbef3cf8366e84eeacba091" \
log,deny,status:403,t:md5,t:hexEncode
Note
Any transformation functions that you specify in a SecRule will be in addition to previous ones specified in SecDefaultAction. Use of "t:none" will remove all transformation functions for the specified rule.
Description: Assigns custom text to a rule or chain.
Action Group: Meta-data
Example:
SecRule REQUEST_FILENAME "\b(?:n(?:map|et|c)|w(?:guest|sh)|cmd(?:32)?|telnet|rcmd|ftp)\.exe\b" \
"t:none,t:lowercase,deny,msg:'System Command Access',id:'950002',\
tag:'WEB_ATTACK/FILE_INJECTION',tag:'OWASP/A2',severity:'2'"
Note
The tag information appears in the error and/or audit log files. Its intent is to be used to automate classification of rules and the alerts generated by rules. Multiple tags can be used per rule/chain.
Description: This action should be used together with an XPath expression to register a namespace.
Action Group: Data
Example:
SecRule REQUEST_HEADERS:Content-Type "text/xml" \
"phase:1,pass,ctl:requestBodyProcessor=XML,ctl:requestBodyAccess=On, \
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
SecRule XML:/soap:Envelope/soap:Body/q1:getInput/id() "123" phase:2,deny