mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
4808 lines
189 KiB
XML
4808 lines
189 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<article>
|
|
<title>ModSecurity Reference Manual</title>
|
|
|
|
<articleinfo>
|
|
<releaseinfo>Version 2.5.0-trunk / (Aug 9, 2007)</releaseinfo>
|
|
|
|
<copyright>
|
|
<year>2004-2007</year>
|
|
|
|
<holder>Breach Security, Inc. (<ulink
|
|
url="http://www.breach.com">http://www.breach.com</ulink>)</holder>
|
|
</copyright>
|
|
</articleinfo>
|
|
|
|
<section id="01-introduction">
|
|
<title>Introduction</title>
|
|
|
|
<para><trademark class="trade">ModSecurity</trademark> is a web
|
|
application firewall (WAF). With over 70% of all attacks now carried out
|
|
over the web application level, organisations need every help they can get
|
|
in making their systems secure. WAFs are deployed to establish an external
|
|
security layer that increases security, detects, and prevents attacks
|
|
before they reach web applications. It provides protection from a range of
|
|
attacks against web applications and allows for HTTP traffic monitoring
|
|
and real-time analysis with little or no changes to existing
|
|
infrastructure.</para>
|
|
|
|
<section>
|
|
<title>HTTP Traffic Logging</title>
|
|
|
|
<para>Web servers are typically well-equipped to log traffic in a form
|
|
useful for marketing analyses, but fall short when it comes to logging
|
|
of traffic to web applications. In particular, most are not capable of
|
|
logging the request bodies. Your adversaries know this, and that is why
|
|
most attacks are now carried out via POST requests, rendering your
|
|
systems blind. ModSecurity makes full HTTP transaction logging possible,
|
|
allowing complete requests and responses to be logged. Its logging
|
|
facilities also allow fine-grained decisions to be made about exactly
|
|
what is logged and when, ensure only the relevant data is
|
|
recorded.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Real-Time Monitoring and Attack Detection</title>
|
|
|
|
<para>In addition to providing logging facilities, ModSecurity can
|
|
monitor the HTTP traffic in real time in order to detect attacks. In
|
|
this case ModSecurity operates as a web intrusion detection tool,
|
|
allowing you to react to suspicious events that take place at your web
|
|
systems.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Attack Prevention and Just-in-time Patching</title>
|
|
|
|
<para>ModSecurity can also act immediately to prevent attacks from
|
|
reaching your web applications. There are three commonly used
|
|
approaches:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>Negative security model. Negative security model monitors
|
|
requests for anomalies, unusual behaviour, and common web
|
|
application attacks. It keeps anomaly scores for each request, IP
|
|
addresses, application sessions, and user accounts. Requests with
|
|
high anomaly scores are either logged or rejected altogether.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Positive security model. When positive security model is
|
|
deployed, only requests that are known to be valid are accepted,
|
|
with everything else rejected. This approach works best with
|
|
applications that are heavily used but rarely updated.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Known weaknesses and vulnerabilities. Its rule language makes
|
|
ModSecurity an ideal external patching tool. External patching is
|
|
all about reducing the window of opportunity. Time needed to patch
|
|
application vulnerabilities often runs to weeks in many
|
|
organisations. With ModSecurity, applications can be patched from
|
|
the outside, without touching the application source code (and even
|
|
without any access to it), making your systems secure until a proper
|
|
patch is produced.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Flexible Rule Engine</title>
|
|
|
|
<para>A flexible rule engine sits in the heart of ModSecurity. It
|
|
implements the ModSecurity Rule Language, which is a specialised
|
|
programming language designed to work with HTTP transaction data. The
|
|
ModSecurity Rule Language was designed to be easy to use, yet flexible:
|
|
common operations are simple while complex operations are possible.
|
|
Certified ModSecurity Rules, included with subscription to ModSecurity,
|
|
contain a comprehensive set of rules that implement general-purpose
|
|
hardening, common web application security issues. Heavily commented,
|
|
these rules can be used as a learning tool.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Embedded-mode Deployment</title>
|
|
|
|
<para>ModSecurity is an embeddable web application firewall, which means
|
|
it can be deployed as part of your existing web server infrastructure
|
|
provided your web servers are Apache-based. This deployment method has
|
|
certain advantages:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>No changes to existing network. It only takes a few minutes to
|
|
add ModSecurity to your existing web servers. And because it was
|
|
designed to be completely passive by default, you are free to deploy
|
|
it incrementally and only use the features you need. It is equally
|
|
easy to remove or deactivate it should decide you don't want it any
|
|
more.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>No single point of failure. Unlike with network-based
|
|
deployments, you will not be introducing a new point of failure to
|
|
your system.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Implicit load balancing and scaling. Because it works embedded
|
|
in web servers, ModSecurity will automatically take advantage of the
|
|
additional load balancing and scalability features. You will not
|
|
need to think of load balancing and scaling unless your existing
|
|
system needs them.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Minimal overhead. Because it works from inside the web server
|
|
process there is no overhead for network communication and minimal
|
|
overhead in parsing and data exchange.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>No problem with encrypted or compressed content. Many IDS
|
|
systems have difficulties analysing SSL traffic. This is not a
|
|
problem for ModSecurity because it is positioned to work when the
|
|
traffic is decrypted and decompressed.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>ModSecurity is known to work well on a wide range of operating
|
|
systems. Our customers are successfully running it on Linux, Windows,
|
|
Solaris, FreeBSD, OpenBSD, NetBSD, AIX, Mac OS X, and HP-UX.<emphasis
|
|
role="bold"></emphasis></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Network-based Deployment</title>
|
|
|
|
<para>ModSecurity works equally well when deployed as part of an
|
|
Apache-based reverse proxy server, and many of our customers choose to
|
|
do so. In this scenario, one installation of ModSecurity can protect any
|
|
number of web servers (even the non-Apache ones).</para>
|
|
</section>
|
|
|
|
<section id="03-licensing">
|
|
<title>Licensing</title>
|
|
|
|
<para>ModSecurity is available under two licenses. Users can choose to
|
|
use the software under the terms of the GNU General Public License
|
|
version 2 (licence text is included with the distribution), as an Open
|
|
Source / Free Software product. A range of commercial licenses is also
|
|
available, together with a range of commercial support contracts. For
|
|
more information on commercial licensing please contact Breach
|
|
Security.</para>
|
|
|
|
<note>
|
|
<para>ModSecurity, mod_security, and ModSecurity Pro are trademarks or
|
|
registered trademarks of Breach Security, Inc.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>ModSecurity Core Rules</title>
|
|
|
|
<section>
|
|
<title>Overview</title>
|
|
|
|
<para>ModSecurity is a web application firewall engine that provides
|
|
very little protection on its own. In order to become useful,
|
|
ModSecurity must be configured with rules. In order to enable users to
|
|
take full advantage of ModSecurity out of the box, Breach Security Inc.
|
|
is providing a free certified rule set for ModSecurity 2.0. Unlike
|
|
intrusion detection and prevention systems, which rely on signature
|
|
specific to known vulnerabilities, the Core Rules provide generic
|
|
protection from unknown vulnerabilities often found in web applications,
|
|
which are in most cases custom coded. The Core Rules are heavily
|
|
commented to allow it to be used as a step-by-step deployment guide for
|
|
ModSecurity. The latest Core Rules can be found at the ModSecurity
|
|
website - <ulink
|
|
url="http://www.modsecurity.org/projects/rules/">http://www.modsecurity.org/projects/rules/</ulink>.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Core Rules Structure</title>
|
|
|
|
<para>If you expect a single pack of Apache configuration files, you are
|
|
right, and wrong. A ModSecurity rule set includes information about
|
|
different areas:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>The logic required to detect attacks.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A policy setting the actions to perform if an attack is
|
|
detected.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Information regarding attacks.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>In order to allow separate management of the different parts, the
|
|
Core Rules are based on templates that are generated into a run-time
|
|
rule set by inserting policy, patterns and event information. The Core
|
|
Rules package includes these templates, the generation script (written
|
|
in Perl) and data files required to generate a useful rule set. It also
|
|
includes a bunch of pre-generated rule sets for different policies. The
|
|
generation script also allows two optimizations:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Optimal use of regular expressions. Since regular expressions
|
|
are much more efficient if assembled into a single expression and
|
|
optimized, the generation script takes the list of patterns that are
|
|
required for a rule and optimize them into a most efficient regular
|
|
expression.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Removal of rules that are not utilized by a specific
|
|
policy.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Core Rules Content</title>
|
|
|
|
<para>In order to provide generic web applications protection, the Core
|
|
Rules use the following techniques:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>HTTP protection - detecting violations of the HTTP protocol
|
|
and a locally defined usage policy.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Common Web Attacks Protection - detecting common web
|
|
application security attack.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Automation detection - Detecting bots, crawlers, scanners and
|
|
other surface malicious activity.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Trojan Protection - Detecting access to Trojans horses.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Error Hiding - Disguising error messages sent by the
|
|
server.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="02-installation">
|
|
<title>Installation</title>
|
|
|
|
<para>ModSecurity installation consists of the following steps:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>ModSecurity 2.x works with Apache 2.0.x or better.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Make sure you have <literal
|
|
moreinfo="none">mod_unique_id</literal> installed.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Install the latest version of libxml2, if it isn't already
|
|
installed on the server.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Unpack the ModSecurity archive</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Edit Makefile to configure the path to the Apache ServerRoot
|
|
directory. You can check this by identifying the ServerRoot directive
|
|
setting in your httpd.conf file. This is the path that was specified
|
|
with the "--install-path=" configuration flag during compilation (for
|
|
example, in Fedora Core4:<filename moreinfo="none"> top_dir =
|
|
/etc/httpd</filename>).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Edit Makefile to configure the correct include path for libxml
|
|
(for example: <filename
|
|
moreinfo="none">INCLUDES=-I/usr/include/libxml2</filename>)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Compile with <literal moreinfo="none">make</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Stop Apache</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Install with<literal moreinfo="none"> make
|
|
install</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>(Optional) Add one line to your configuration to load libxml2:
|
|
<filename moreinfo="none">LoadFile
|
|
/usr/lib/libxml2.so</filename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Add one line to your configuration to load ModSecurity: <literal
|
|
moreinfo="none">LoadModule security2_module
|
|
modules/mod_security2.so</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Configure ModSecurity</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Start Apache</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>You now have ModSecurity 2.x up and running.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<note>
|
|
<para>If you have compiled Apache yourself you might experience problems
|
|
compiling ModSecurity against PCRE. This is because Apache bundles PCRE
|
|
but this library is also typically provided by the operating system. I
|
|
would expect most (all) vendor-packaged Apache distributions to be
|
|
configured to use an external PCRE library (so this should not be a
|
|
problem).</para>
|
|
|
|
<para>You want to avoid Apache using the bundled PCRE library and
|
|
ModSecurity linking against the one provided by the operating system.
|
|
The easiest way to do this is to compile Apache against the PCRE library
|
|
provided by the operating system (or you can compile it against the
|
|
latest PCRE version you downloaded from the main PCRE distribution
|
|
site). You can do this at configure time using the<literal
|
|
moreinfo="none"> --with-pcre</literal> switch. If you are not in a
|
|
position to recompile Apache then, to compile ModSecurity successfully,
|
|
you'd still need to have access to the bundled PCRE headers (they are
|
|
available only in the Apache source code) and change the include path
|
|
for ModSecurity (as you did in step 7 above) to point to them.</para>
|
|
|
|
<para>Do note that if your Apache is using an external PCRE library you
|
|
can compile ModSecurity with <literal
|
|
moreinfo="none">WITH_PCRE_STUDY</literal> defined,which would possibly
|
|
give you a slight performance edge in regular expression
|
|
processing.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="03-configuration-directives">
|
|
<title>Configuration Directives</title>
|
|
|
|
<para>The following section outlines all of the ModSecurity directives.
|
|
Most of the ModSecurity directives can be used inside the various Apache
|
|
Scope Directives such as <literal>VirtualHost</literal>,
|
|
<literal>Location</literal>, <literal>LocationMatch</literal>,
|
|
<literal>Directory</literal>, etc... There are others, however, that can
|
|
only be used once in the main configuration file. This information is
|
|
specified in the Scope sections below.</para>
|
|
|
|
<para>These rules, along with the Core rules files, should be contained is
|
|
files outside of the httpd.conf file and called up with Apache "Include"
|
|
directives. This allows for easier updating/migration of the rules. If you
|
|
create your own custom rules that you would like to use with the Core
|
|
rules, you should create a file called -
|
|
<filename>modsecurity_crs_15_customrules.conf</filename> and place it in
|
|
the same directory as the Core rules files. By using this file name, your
|
|
custom rules will be called up after the standard ModSecurity Core rules
|
|
configuration file but before the other Core rules. This allows your rules
|
|
to be evaluate first which can be useful if you need to implement specific
|
|
"allow" rules or to correct any false positives in the Core rules as they
|
|
are applied to your site.</para>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>It is highly encouraged that you do not edit the Core rules files
|
|
themselves but rather place all changes (such as
|
|
<literal>SecRuleRemoveByID</literal>, etc...) in your custom rules file.
|
|
This will allow for easier upgrading as newer Core rules are released by
|
|
Breach Security on the ModSecurity website.</para>
|
|
|
|
<section>
|
|
<title><literal>SecAction</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Unconditionally
|
|
processes the action list it receives as the first and only parameter.
|
|
It accepts one parameter, the syntax of which is identical to the third
|
|
parameter of<literal moreinfo="none"> SecRule</literal>.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAction action1,action2,action2</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAction
|
|
nolog,redirect:http://www.hostname.com</literal></para>
|
|
|
|
<para><emphasis role="bold">ProcessingPhase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
|
|
<para>SecAction is best used when you uncondiationally execute an
|
|
action. This is explicit triggering whereas the normal Actions are
|
|
conditional based on data inspection of the request/response. This is a
|
|
useful directive when you want to run certian actions such as initcol to
|
|
initialize collections.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecArgumentSeparator</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Specifies which
|
|
character to use as separator for<literal moreinfo="none">
|
|
application/x-www-form-urlencoded</literal> content. Defaults to
|
|
<literal moreinfo="none">&</literal>. Applications are sometimes
|
|
(very rarely) written to use a semicolon (<literal
|
|
moreinfo="none">;</literal>).</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecArgumentSeparator character</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecArgumentSeparator ;</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold"> <emphasis role="bold">Scope:</emphasis>
|
|
</emphasis> Main</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
|
|
<para>This directive is needed if a backend web appliaction is using a
|
|
non-standard argument separator. If this directive is not set properly
|
|
for each web app, then ModSecurity will not be able to parse the
|
|
arguements appropriately and the effectiveness of the rule matching will
|
|
be significantly decreased.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditEngine</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the audit
|
|
logging engine.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditEngine On|Off|RelevantOnly</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditEngine On</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Can be
|
|
set/changed with the "ctl" action for the current transaction.</para>
|
|
|
|
<para>Example: The following example shows the various audit directives
|
|
used together.</para>
|
|
|
|
<programlisting format="linespecific"><emphasis role="bold">SecAuditEngine RelevantOnly</emphasis>
|
|
SecAuditLog logs/audit/audit.log
|
|
SecAuditLogParts ABCFHZ
|
|
SecAuditLogType concurrent
|
|
SecAuditLogStorageDir logs/audit
|
|
<emphasis role="bold">SecAuditLogRelevantStatus ^[45]</emphasis></programlisting>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - log all transactions
|
|
by default.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - do not log
|
|
transactions by default.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">RelevantOnly</literal> - by default
|
|
only log transactions that have triggered a warning or an error, or
|
|
have a status code that is considered to be relevant (see<literal
|
|
moreinfo="none"> SecAuditLogRelevantStatus</literal>).</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditLog</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the path to
|
|
the main audit log file.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditLog /path/to/auditlog</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditLog
|
|
/usr/local/apache/logs/audit.log</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This file is
|
|
open on startup when the server typically still runs as<emphasis>
|
|
root</emphasis>. You should not allow non-root users to have write
|
|
privileges for this file or for the directory it is stored in..</para>
|
|
|
|
<para>This file will be used to store the audit log entries if serial
|
|
audit logging format is used. If concurrent audit logging format is used
|
|
this file will be used as an index, and contain a record of all audit
|
|
log files created. If you are planning to use Concurrent audit logging
|
|
and sending your audit log data off to a remote Console host, then you
|
|
will need to use the modsec-auditlog-collector.pl script and use the
|
|
following format:</para>
|
|
|
|
<para><programlisting format="linespecific">SecAuditLog \
|
|
"|/path/modsec-auditlog-collector.pl /path/SecAuditLogDataDir /path/SecAuditLog"</programlisting></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditLog2</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the path to
|
|
the secondary audit log index file when concurrent logging is enabled.
|
|
See <literal moreinfo="none">SecAuditLog2</literal> for more
|
|
details.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditLog2 /path/to/auditlog2</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditLog2
|
|
/usr/local/apache/logs/audit2.log</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> A main audit
|
|
log must be defined via <literal moreinfo="none">SecAuditLog</literal>
|
|
before this directive may be used. Additionally, this log is only used
|
|
for replicating the main audit log index file when concurrent audit
|
|
logging is used. It will <emphasis role="bold">not</emphasis> be used
|
|
for non-concurrent audit logging.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditLogParts</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the path to
|
|
the main audit log file.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogParts PARTS</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogParts ABCFHZ</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold"> <emphasis role="bold">Scope:</emphasis>
|
|
</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> At this time
|
|
ModSecurity does not log response bodies of stock Apache responses (e.g.
|
|
<literal moreinfo="none">404</literal>), or the <literal
|
|
moreinfo="none">Server</literal> and <literal
|
|
moreinfo="none">Date</literal> response headers.</para>
|
|
|
|
<para>Default:<literal moreinfo="none"> ABCFHZ</literal>.</para>
|
|
|
|
<para>Available audit log parts:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">A</literal> - audit log header
|
|
(mandatory)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">B</literal> - request headers</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">C</literal> - request body (present
|
|
only if the request body exists and ModSecurity is configured to
|
|
intercept it)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">D</literal> - RESERVED for
|
|
intermediary response headers, not implemented yet.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">E</literal> - intermediary response
|
|
body (present only if ModSecurity is configured to intercept
|
|
response bodies, and if the audit log engine is configured to record
|
|
it). Intermediary response body is the same as the actual response
|
|
body unless ModSecurity intercepts the intermediary response body,
|
|
in which case the actual response body will contain the error
|
|
message (either the Apache default error message, or the
|
|
ErrorDocument page).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">F</literal> - final response headers
|
|
(excluding the Date and Server headers, which are always added by
|
|
Apache in the late stage of content delivery).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">G</literal> - RESERVED for the actual
|
|
response body, not implemented yet.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">H</literal> - audit log
|
|
trailer</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">I</literal> - This part is a
|
|
replacement for part C. It will log the same data as C in all cases
|
|
except when<literal moreinfo="none">multipart/form-data</literal>
|
|
encoding in used. In this case it will log a fake <literal
|
|
moreinfo="none"> application/x-www-form-urlencoded</literal> body
|
|
that contains the information about parameters but not about the
|
|
files. This is handy if you don't want to have (often large) files
|
|
stored in your audit logs.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">J</literal> - RESERVED. This part,
|
|
when implemented, will contain information about the files uploaded
|
|
using multipart/form-data encoding.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Z</literal> - final boundary,
|
|
signifies the end of the entry (mandatory)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditLogRelevantStatus</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures which
|
|
response status code is to be considered relevant for the purpose of
|
|
audit logging.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogRelevantStatus REGEX</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogRelevantStatus ^[45]</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Must have the
|
|
SecAuditEngine set to RelevantOnly. The parameter is a regular
|
|
expression.</para>
|
|
|
|
<para>The main purpose of this directive is to allow you to configure
|
|
audit logging for only transactions that generate the specified HTTP
|
|
Response Status Code. This directive is often used to the decrease the
|
|
total size of the audit log file. Keep in mind that if this parameter is
|
|
used, then successful attacks that result in a 200 OK status code will
|
|
not be logged.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditLogStorageDir</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
storage directory where concurrent audit log entries are to be
|
|
stored.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogStorageDir
|
|
/path/to/storage/dir</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogStorageDir
|
|
/usr/local/apache/logs/audit</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis>
|
|
SecAuditLogType must be set to Concurrent. The directory must already be
|
|
created before starting Apache and it must be writable by the web server
|
|
user as new files are generated at runtime.</para>
|
|
|
|
<para>As with all logging mechanisms, ensure that you specify a file
|
|
system location that has adequate disk space and is not on the root
|
|
partition.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecAuditLogType</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the type
|
|
of audit logging mechanism to be used.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogType Serial|Concurrent</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecAuditLogType Serial</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Must specify
|
|
SecAuditLogStorageDir if you use concurrent logging.</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para><literal moreinfo="none">Serial</literal> - all audit log
|
|
entries will be stored in the main audit logging file. This is more
|
|
convenient for casual use but it is slower as only one audit log
|
|
entry can be written to the file at any one file.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Concurrent</literal> - audit log
|
|
entries will be stored in separate files, one for each transaction.
|
|
Concurrent logging is the mode to use if you are going to send the
|
|
audit log data off to a remote ModSecurity Console host.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecCacheTransformations</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Controls caching of
|
|
transformations.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecCacheTransformations On|Off
|
|
[options]</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecCacheTransformations On
|
|
"minlen:64,maxlen:0"</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> N/A</para>
|
|
|
|
<para>First parameter:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - cache transformations
|
|
(per transaction, per phase) allowing identical transformations to
|
|
be performed only once. (default)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - do not cache any
|
|
transformations, forcing all transformations to be performed for
|
|
each rule executed.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The following options are allowed (comma seperated):</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">minlen:N</literal> - do not cache the
|
|
transformation if the value's length is less than N bytes. (default:
|
|
15)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">maxlen:N</literal> - do not cache the
|
|
transformation if the value's length is more than N bytes. A zero
|
|
value is interpreted as "unlimited". (default: 0)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecChrootDir</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
directory path that will be used to jail the web server process.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecChrootDir /path/to/chroot/dir</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecChrootDir /chroot</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Main</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> The internal
|
|
chroot functionality provided by ModSecurity works great for simple
|
|
setups. One example of a simple setup is Apache serving static files
|
|
only, or running scripts using modules. For more complex setups you
|
|
should consider building a jail the old-fashioned way. The internal
|
|
chroot feature should be treated as somewhat experimental. Due to the
|
|
large number of default and third-party modules available for the Apache
|
|
web server, it is not possible to verify the internal chroot works
|
|
reliably with all of them. You are advised to think about your option
|
|
and make your own decision. In particular, if you are using any of the
|
|
modules that fork in the module initialisation phase (e.g. mod_fastcgi,
|
|
mod_fcgid, mod_cgid), you are advised to examine each Apache process and
|
|
observe its current working directory, process root, and the list of
|
|
open files.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecContentInjection (Experimental)</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Enables content
|
|
injection using actions <literal>append</literal> and
|
|
<literal>prepend</literal>.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis>
|
|
<literal>SecContentInjection (On|Off)</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis>
|
|
<literal>SecContentInjection On</literal></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecCookieFormat</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Selects the cookie
|
|
format that will be used in the current configuration context.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecCookieFormat 0|1</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecCookieFormat 0</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">0</literal> - use version 0
|
|
(Netscape) cookies. This is what most applications use. It is the
|
|
default value.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">1</literal> - use version 1
|
|
cookies.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecDataDir</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Path where
|
|
persistent data (e.g. IP address data, session data, etc) is to be
|
|
stored.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecDataDir /path/to/dir</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecDataDir /usr/local/apache/logs/data</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold"> <emphasis role="bold">Scope:</emphasis>
|
|
</emphasis> Main</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes: </emphasis> This
|
|
directive is needed when initcol, setsid an setuid are used. Must be
|
|
writable by the web server user.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecDebugLog</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Path to the
|
|
ModSecurity debug log file.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecDebugLog /path/to/modsec-debug.log</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecDebugLog
|
|
/usr/local/apache/logs/modsec-debug.log</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecDebugLogLevel</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
verboseness of the debug log data.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecDebugLogLevel 0|1|2|3|4|5|6|7|8|9</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecDebugLogLevel 4</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Levels
|
|
<literal moreinfo="none">1 - 3</literal> are always sent to the Apache
|
|
error log. Therefore you can always use level <literal
|
|
moreinfo="none">0</literal> as the default logging level in production.
|
|
Level <literal moreinfo="none">5</literal> is useful when debugging. It
|
|
is not advisable to use higher logging levels in production as excessive
|
|
logging can slow down server significantly.</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">0</literal> - no logging.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">1</literal> - errors (intercepted
|
|
requests) only.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">2</literal> - warnings.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">3</literal> - notices.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">4</literal> - details of how
|
|
transactions are handled.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">5</literal> - as above, but including
|
|
information about each piece of information handled.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">9</literal> - log everything,
|
|
including very detailed debugging information.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecDefaultAction</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the default
|
|
action to take on a rule match.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecDefaultAction
|
|
action1,action2,action3</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecDefaultAction
|
|
log,auditlog,deny,status:403,phase:2,t:lowercase</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Rules
|
|
following a SecDefaultAction directive will inherit this setting unless
|
|
a specific action is specified for an indivdual rule or until another
|
|
SecDefaultAction is specified.</para>
|
|
|
|
<para>The default value is:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,auditlog,deny,status:403,phase:2,t:none</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>SecDefaultAction must specify a disruptive action and a processing
|
|
phase.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecGeoLookupsDb</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the path to
|
|
the geograpical database file.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecGeoLookupsDb /path/to/db</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecGeoLookupsDb
|
|
/usr/local/geo/data/GeoLiteCity.dat</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Check out
|
|
www.maxmind.com for free database files.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecGuardianLog</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configuration
|
|
directive to use the httpd-guardian script to monitor for Denial of
|
|
Service (DoS) attacks.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecGuardianLog |/path/to/httpd-guardian</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecGuardianLog
|
|
|/usr/local/apache/bin/httpd-guardian</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Main</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> By default
|
|
httpd-guardian will defend against clients that send more 120 requests
|
|
in a minute, or more than 360 requests in five minutes.</para>
|
|
|
|
<para>Since 1.9, ModSecurity supports a new directive, SecGuardianLog,
|
|
that is designed to send all access data to another program using the
|
|
piped logging feature. Since Apache is typically deployed in a
|
|
multi-process fashion, making information sharing difficult, the idea is
|
|
to deploy a single external process to observe all requests in a
|
|
stateful manner, providing additional protection.</para>
|
|
|
|
<para>Development of a state of the art external protection tool will be
|
|
a focus of subsequent ModSecurity releases. However, a fully functional
|
|
tool is already available as part of the <ulink type=""
|
|
url="http://www.apachesecurity.net/tools/">Apache httpd tools
|
|
project</ulink>. The tool is called httpd-guardian and can be used to
|
|
defend against Denial of Service attacks. It uses the blacklist tool
|
|
(from the same project) to interact with an iptables-based (Linux) or
|
|
pf-based (*BSD) firewall, dynamically blacklisting the offending IP
|
|
addresses. It can also interact with SnortSam (http://www.snortsam.net).
|
|
Assuming httpd-guardian is already configured (look into the source code
|
|
for the detailed instructions) you only need to add one line to your
|
|
Apache configuration to deploy it:</para>
|
|
|
|
<programlisting format="linespecific">SecGuardianLog |/path/to/httpd-guardian</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecPdfProtect</literal> (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Enables the PDF XSS
|
|
protection functionality. Once enabled access to PDF files is tracked.
|
|
Direct access attempts are redirected to links that contain one-time
|
|
tokens. Requests with valid tokens are allowed through unmodified.
|
|
Requests with invalid tokens are also allowed through but with forced
|
|
download of the PDF files. This implementation uses response headers to
|
|
detect PDF files and thus can be used with dynamically generated PDF
|
|
files that do not have the <filename>.pdf</filename> extension in the
|
|
request URI.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecPdfProtectMethod</literal> (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configure desired
|
|
protection method to be used when requests for PDF files are detected.
|
|
Possible values are <literal>TokenRedirection</literal> and
|
|
<literal>ForcedDownload</literal>. The token redirection approach will
|
|
attempt to redirect with tokens where possible. This allows PDF files to
|
|
continue to be opened inline but only works for GET requests. Forced
|
|
download always causes PDF files to be delivered as opaque binaries and
|
|
attachments. The latter will always be used for non-GET requests. Forced
|
|
download is considered to be more secure but may cause usability
|
|
problems for users ("This PDF won't open anymore!").</para>
|
|
|
|
<para><emphasis role="bold">Default:</emphasis>
|
|
<literal>TokenRedirection</literal></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecPdfProtectSecret</literal> (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the secret
|
|
that will be used to construct one-time tokens. You should use a
|
|
reasonably long value for the secret (e.g. 16 characters is good). Once
|
|
selected the secret should not be changed as as it will break the the
|
|
tokens that were sent prior to change. But it's not a big deal even if
|
|
you change it. It will just force dowload of PDF files with tokens that
|
|
were issued in the last few seconds.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecPdfProtectTimeout</literal> (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the token
|
|
timeout. After token expires it can no longer be used to allow access to
|
|
PDF file. Request will be allowed through but the PDF will be delivered
|
|
as attachment.</para>
|
|
|
|
<para><emphasis role="bold">Default:</emphasis>
|
|
<literal>10</literal></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecPdfProtectTokenName</literal> (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Defines the name of
|
|
the token. The only reason you would want to change the name of the
|
|
token is if you wanted to hide the fact you are running ModSecurity.
|
|
It's a good reason but it won't really help as the adversary can look
|
|
into the algorithm used for PDF protection and figure it out anyway. It
|
|
does raise the bar slightly so go ahead if you want to.</para>
|
|
|
|
<para><emphasis role="bold">Default:</emphasis>
|
|
<literal>PDFTOKEN</literal></para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRequestBodyAccess</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures whether
|
|
request bodies will be buffered and processed by ModSecurity by
|
|
default.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRequestBodyAccess On|Off</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRequestBodyAccess On</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This
|
|
directive is required if you plan to inspect POST_PAYLOADS of requests.
|
|
This directive must be used along with the "phase:2" processing phase
|
|
action and REQUEST_BODY variable/location. If any of these 3 parts are
|
|
not configured, you will not be able to inspect the request
|
|
bodies.</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - access request
|
|
bodies.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - do not attempt to
|
|
access request bodies.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRequestBodyLimit</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
maximum request body size ModSecurity will accept for buffering.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRequestBodyLimit NUMBER_IN_BYTES</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRequestBodyLimit 134217728</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> 131072 KB
|
|
(134217728 bytes) is the default setting. Anything over this limit will
|
|
be rejected with status code 413 Request Entity Too Large. There is a
|
|
hard limit of 1 GB.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRequestBodyInMemoryLimit</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
maximum request body size ModSecurity will store in memory.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRequestBodyInMemoryLimit
|
|
NUMBER_IN_BYTES</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRequestBodyInMemoryLimit 131072</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
|
|
<para>By default the limit is 128 KB:</para>
|
|
|
|
<programlisting format="linespecific"># Store up to 128 KB in memory
|
|
SecRequestBodyInMemoryLimit 131072</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecResponseBodyLimit</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
maximum response body size that will be accepted for buffering.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyLimit NUMBER_IN_BYTES</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyLimit 524228</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Anything over
|
|
this limit will be rejected with status code 500 Internal Server Error.
|
|
This setting will not affect the responses with MIME types that are not
|
|
marked for buffering. There is a hard limit of 1 GB.</para>
|
|
|
|
<para>By default this limit is configured to 512 KB:</para>
|
|
|
|
<programlisting format="linespecific"># Buffer response bodies of up to 512 KB in length
|
|
SecResponseBodyLimit 524288</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecResponseBodyMimeType</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures
|
|
which<literal moreinfo="none"> MIME</literal> types are to be considered
|
|
for response body buffering.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyMimeType mime/type</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyMimeType text/plain
|
|
text/html</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis>
|
|
Multiple<literal moreinfo="none"> SecResponseBodyMimeType</literal>
|
|
directives can be used to add<literal moreinfo="none"> MIME</literal>
|
|
types.</para>
|
|
|
|
<para>The default value is <literal
|
|
moreinfo="none">text/plaintext/html</literal>:</para>
|
|
|
|
<programlisting format="linespecific">SecResponseBodyMimeType text/plain text/html</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecResponseBodyMimeTypesClear</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Clears the list of
|
|
<literal moreinfo="none">MIME</literal> types considered for response
|
|
body buffering, allowing you to start populating the list from
|
|
scratch.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyMimeTypesClear</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyMimeTypesClear</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecResponseBodyAccess</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures whether
|
|
response bodies are to be buffer and analysed or not.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyAccess On|Off</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecResponseBodyAccess On</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This
|
|
directive is required if you plan to inspect html responses. This
|
|
directive must be used along with the "phase:4" processing phase action
|
|
and RESPONSE_BODY variable/location. If any of these 3 parts are not
|
|
configured, you will not be able to inspect the response bodies.</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - access response bodies
|
|
(but only if the MIME type matches, see above).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - do not attempt to
|
|
access response bodies.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRule</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> <literal
|
|
moreinfo="none">SecRule</literal> is the main ModSecurity directive. It
|
|
is used to analyse data and perform actions based on the results.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRule VARIABLES OPERATOR [ACTIONS]</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRule REQUEST_URI "attack"</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> None</para>
|
|
|
|
<para>In general, the format of this rule is as follows:</para>
|
|
|
|
<programlisting format="linespecific">SecRule VARIABLES OPERATOR [ACTIONS]</programlisting>
|
|
|
|
<para>The second part, <literal moreinfo="none">OPERATOR</literal>,
|
|
specifies how they are going to be checked. The third (optional) part,
|
|
<literal moreinfo="none">ACTIONS</literal>, specifies what to do
|
|
whenever the operator used performs a successful match against a
|
|
variable.</para>
|
|
|
|
<section>
|
|
<title>Variables in rules</title>
|
|
|
|
<para>The first part,<literal moreinfo="none"> VARIABLES</literal>,
|
|
specifies which variables are to be checked. For example, the
|
|
following rule will reject a transaction that has the word<emphasis>
|
|
dirty</emphasis> in the URI:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_URI dirty</programlisting>
|
|
|
|
<para>Each rule can specify one or more variables:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_URI|QUERY_STRING dirty</programlisting>
|
|
|
|
<para>There is a third format supported by the selection operator -
|
|
XPath expression. XPath expressions can only used against the special
|
|
variable XML, which is available only of the request body was
|
|
processed as XML.</para>
|
|
|
|
<programlisting format="linespecific">SecRule XML:/xPath/Expression dirty</programlisting>
|
|
|
|
<note>
|
|
<para>As you have just seen, not all collections support all
|
|
selection operator format types. You should refer to the
|
|
documentation of each collection to determine what is and isn't
|
|
supported.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Operators in rules</title>
|
|
|
|
<para>In the simplest possible case you will use a regular expression
|
|
pattern as the second rule parameter. This is what we've done in the
|
|
examples above. If you do this ModSecurity assumes you want to use the
|
|
<literal moreinfo="none">rx</literal> operator. You can explicitly
|
|
specify the operator you want to use by using <literal
|
|
moreinfo="none">@</literal> as the first character in the second rule
|
|
parameter:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_URI "@rx dirty"</programlisting>
|
|
|
|
<para>Note how we had to use double quotes to delimit the second rule
|
|
parameter. This is because the second parameter now has a whitespace
|
|
in it. Any number of whitespace characters can follow the name of the
|
|
operator. If there are any non-whitespace characters there, they will
|
|
all be treated as a special parameter to the operator. In the case of
|
|
the regular expression operator the special parameter is the pattern
|
|
that will be used for comparison.</para>
|
|
|
|
<para>The @ can be the second character if you are using negation to
|
|
negate the result returned by the operator:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &ARGS "!@rx ^0$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Actions in rules</title>
|
|
|
|
<para>The third parameter, <literal moreinfo="none">ACTIONS</literal>,
|
|
can be omitted only because there is a helper feature that specifies
|
|
the default action list. If the parameter isn't omitted the actions
|
|
specified in the parameter will be merged with the default action list
|
|
to create the actual list of actions that will be processed on a rule
|
|
match.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRuleInheritance</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures whether
|
|
the current context will inherit rules from the parent context
|
|
(configuration options are inherited in most cases - you should look up
|
|
the documentation for every directive to determine if it is inherited or
|
|
not).</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRuleInheritance On|Off</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRuleInheritance Off</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis>
|
|
Resource-specific contexts (e.g.<literal moreinfo="none">
|
|
Location</literal>, <literal moreinfo="none">Directory</literal>, etc)
|
|
cannot override <emphasis>phase1</emphasis> rules configured in the main
|
|
server or in the virtual server. This is because phase 1 is run early in
|
|
the request processing process, before Apache maps request to resource.
|
|
Virtual host context can override phase 1 rules configured in the main
|
|
server.</para>
|
|
|
|
<para>Example: The following example shows where ModSecurity may be
|
|
enabled in the main Apache configuration scope, however you might want
|
|
to configure your VirtualHosts differently. In the first example, the
|
|
first virtualhost is not inheriting the ModSecurity main config
|
|
directives and in the second one it is.</para>
|
|
|
|
<programlisting format="linespecific">SecRuleEnine On
|
|
SecDefaultAction log,pass,phase:2
|
|
...
|
|
|
|
<VirtualHost *:80>
|
|
ServerName app1.com
|
|
ServerAlias www.app1.com<emphasis role="bold">
|
|
SecRuleInheritance Off</emphasis>
|
|
SecDefaultAction log,deny,phase:1,redirect:http://www.site2.com
|
|
...
|
|
</VirtualHost>
|
|
|
|
<VirtualHost *:80>
|
|
ServerName app2.com
|
|
ServerAlias www.app2.com
|
|
<emphasis role="bold">SecRuleInheritance On</emphasis> SecRule ARGS "attack"
|
|
...
|
|
</VirtualHost></programlisting>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - inherit rules from the
|
|
parent context.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - do not inherit rules
|
|
from the parent context.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRuleEngine</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the rules
|
|
engine.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRuleEngine On|Off|DetectionOnly</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRuleEngine On</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Thisdirective
|
|
can also be controled by the ctl action (ctl:ruleEngine=off) for per
|
|
rule processing.</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - process rules.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - do not process
|
|
rules.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">DetectionOnly</literal> - process
|
|
rules but never intercept transactions, even when rules are
|
|
configured to do so.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRuleRemoveById</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Removes matching
|
|
rules from the parent contexts.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRuleRemoveById RULEID</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRuleRemoveByID 1 2 "9000-9010"</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This
|
|
directive supports multiple parameters, where each parameter can either
|
|
be a rule ID, or a range. Parameters that contain spaces must be
|
|
delimited using double quotes.</para>
|
|
|
|
<programlisting format="linespecific">SecRuleRemoveById 1 2 5 10-20 "400-556" 673</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecRuleRemoveByMsg</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Removes matching
|
|
rules from the parent contexts.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecRuleRemoveByMsg REGEX</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecRuleRemoveByMsg "FAIL"</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This
|
|
directive supports multiple parameters. Each parameter is a regular
|
|
expression that will be applied to the message (specified using the
|
|
<literal moreinfo="none">msg</literal> action).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecServerSignature</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Instructs
|
|
ModSecurity to change the data presented in the "Server:" response
|
|
header token.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecServerSignature "WEB SERVER
|
|
SOFTWARE"</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecServerSignature
|
|
"Netscape-Enterprise/6.0"</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Main</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> In order for
|
|
this directive to work, you must set the Apache ServerTokens directive
|
|
to Full. ModSecurity will overwrite the server signature data held in
|
|
this memory space with the data set in this directive. If ServerTokens
|
|
is not set to Full, then the memory space is most likely not large
|
|
enough to hold the new data we are looking to insert.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecTmpDir</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
directory where temporary files will be created.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecTmpDir /path/to/dir</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecTmpDir /tmp</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Needs to be
|
|
writable by the Apache user process. This is the directory location
|
|
where Apache will swap data to disk if it runs out of memory (more data
|
|
than what was specified in the SecRequestBodyInMemoryLimit directive)
|
|
during inspection.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecUploadDir</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures the
|
|
directory where intercepted files will be stored.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecUploadDir /path/to/dir</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecUploadDir /tmp</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This
|
|
directory must be on the same filesystem as the temporary directory
|
|
defined with <literal moreinfo="none">SecTmpDir</literal>. This
|
|
directive is used with <literal>SecUploadKeepFiles</literal>.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecUploadKeepFiles</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configures whether
|
|
or not the intercepted files will be kept after transaction is
|
|
processed.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecUploadKeepFiles On|Off|RelevantOnly</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecUploadKeepFiles On</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> This
|
|
directive requires the storage directory to be defined (using <literal
|
|
moreinfo="none">SecUploadDir</literal>).</para>
|
|
|
|
<para>Possible values are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">On</literal> - Keep uploaded
|
|
files.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">Off</literal> - Do not keep uploaded
|
|
files.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">RelevantOnly</literal> - This will
|
|
keep only those files that belong to requests that are deemed
|
|
relevant.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>SecWebAppId</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Creates a partition
|
|
on the server that belongs to one web application.</para>
|
|
|
|
<para><emphasis role="bold">Syntax:</emphasis> <literal
|
|
moreinfo="none">SecWebAppId "NAME"</literal></para>
|
|
|
|
<para><emphasis role="bold">Example Usage:</emphasis> <literal
|
|
moreinfo="none">SecWebAppId "WebApp1"</literal></para>
|
|
|
|
<para><emphasis role="bold">Processing Phase:</emphasis> N/A</para>
|
|
|
|
<para><emphasis role="bold">Scope:</emphasis> Any</para>
|
|
|
|
<para><emphasis role="bold">Dependencies/Notes:</emphasis> Partitions
|
|
are used to avoid collisions between session IDs and user IDs. This
|
|
directive must be used if there are multiple applications deployed on
|
|
the same server. If it isn't used, a collision between session IDs might
|
|
occur. The default value is<literal moreinfo="none"> default</literal>.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific"><VirtualHost *:80>
|
|
ServerName app1.com
|
|
ServerAlias www.app1.com
|
|
<emphasis role="bold">SecWebAppId "App1"</emphasis>
|
|
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
|
|
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
|
|
...
|
|
</VirtualHost>
|
|
|
|
<VirtualHost *:80>
|
|
ServerName app2.com
|
|
ServerAlias www.app2.com<emphasis role="bold">
|
|
SecWebAppId "App2"</emphasis>
|
|
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
|
|
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
|
|
...
|
|
</VirtualHost></programlisting>
|
|
|
|
<para>In the two examples configurations shown, SecWebAppId is being
|
|
used in conjuction with the Apache VirtualHost directives. What this
|
|
achieves is to create more unique collection names when being hosted on
|
|
one server. Normally, when setsid is used, ModSecurity will create a
|
|
collection with the name "SESSION" and it will hold the value specified.
|
|
With using SecWebAppId as shown in the examples, however, the name of
|
|
the collection would become "App1_SESSION" and "App2_SESSION".</para>
|
|
|
|
<para>SecWebAppId is relevant in two cases:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>You are logging transactions/alerts to the ModSecurity Console
|
|
and you want to use the web application ID to search only the
|
|
transactions belonging to that application.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>You are using the data persistence facility (collections
|
|
SESSION and USER) and you need to avoid collisions between sessions
|
|
and users belonging to different applications.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="04-processing-phases">
|
|
<title>Processing Phases</title>
|
|
|
|
<para>ModSecurity 2.x allows rules to be placed in one of the following
|
|
five phases:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>Request headers</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Request body</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Response headers</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Response body</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Logging</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para><emphasis role="bold">ModSecurity Processing Phases
|
|
Diagram</emphasis></para>
|
|
|
|
<para><emphasis> <emphasis>Below is a diagram of the standard Apache
|
|
Request Cycle. In the diagram, the 5 ModSecurity processing phases are
|
|
shown.</emphasis> </emphasis></para>
|
|
|
|
<para><graphic fileref="apache_request_cycle-modsecurity.jpg" scale="150"
|
|
scalefit="" /></para>
|
|
|
|
<para>In order to select the phase a rule executes during, use the phase
|
|
action either directly in the rule or in using the
|
|
<literal>SecDefaultAction</literal> directive:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction "log,pass,<emphasis
|
|
role="bold">phase:2</emphasis>"
|
|
SecRule REQUEST_HEADERS:Host "!^$" "deny,<emphasis role="bold">phase:1</emphasis>"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note on Rule and Phases</emphasis></para>
|
|
|
|
<para>Keep in mind that rules are executed according to phases, so even if
|
|
two rules are adjacent in a configuration file, but are set to execute in
|
|
different phases, they would not happen one after the other. The order of
|
|
rules in the configuration file is important only within the rules of each
|
|
phase. This is especially important when using the <literal>skip</literal>
|
|
action.</para>
|
|
|
|
<section>
|
|
<title>Phase Request Headers</title>
|
|
|
|
<para>Rules in this phase are processed immediately after Apache
|
|
completes reading the request headers (post-read-request phase). At this
|
|
point the request body has not been read yet, meaning not all request
|
|
arguments are available. Rules should be placed in this phase if you
|
|
need to have them run early (before Apache does something with the
|
|
request), to do something before the request body has been read,
|
|
determine whether or not the request body should be buffered, or decide
|
|
how you want the request body to be processed (e.g. whether to parse it
|
|
as XML or not).</para>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Rules in this phase can not leverage Apache scope directives
|
|
(Directory, Location, LocationMatch, etc...) as the post-read-request
|
|
hook does not have this information yet. The exception here is the
|
|
VirtualHost directive. If you want to use ModSecurity rules inside
|
|
Apache locations, then they should run in Phase 2. Refer to the Apache
|
|
Request Cycle/ModSecurity Processing Phases diagram.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Phase Request Body</title>
|
|
|
|
<para>This is the general-purpose input analysis phase. Most of the
|
|
application-oriented rules should go here. In this phase you are
|
|
guaranteed to have received the request argument (provided the request
|
|
body has been read). ModSecurity supports three encoding types for the
|
|
request body phase:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>application/x-www-form-urlencoded - used to transfer form
|
|
data</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>multipart/form-data - used for file transfers</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>text/xml - used for passing XML data</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Other encodings are not used by most web applications.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Phase Response Headers</title>
|
|
|
|
<para>This phase takes place just before response headers are sent back
|
|
to the client. Run here if you want to observe the response before that
|
|
happens, and if you want to use the response headers to determine if you
|
|
want to buffer the response body. Note that some response status codes
|
|
(such as 404) are handled earlier in the request cycle by Apache and my
|
|
not be able to be triggered as expected. Additionally, there are some
|
|
response headers that are added by Apache at a later hook (such as Date,
|
|
Server and Connection) that we would not be able to trigger on or
|
|
sanitize. This should work appropirately in a proxy setup or within
|
|
phase:5 (logging).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Phase Response Body</title>
|
|
|
|
<para>This is the general-purpose output analysis phase. At this point
|
|
you can run rules against the response body (provided it was buffered,
|
|
of course). This is the phase where you would want to inspect the
|
|
outbound html for information discloure, error messages or failed
|
|
authentication text.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Phase Logging</title>
|
|
|
|
<para>This phase is run just before logging takes place. The rules
|
|
placed into this phase can only affect how the logging is performed.
|
|
This phase can be used to inspect the error messages logged by Apache.
|
|
You can not deny/block connections in this phase as it is too late. This
|
|
phase also allows for inspection of other response headers that weren't
|
|
available during phase:3 or phase:4.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="05-variables">
|
|
<title>Variables</title>
|
|
|
|
<para>The following variables are supported in ModSecurity 2.x:</para>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS</literal></title>
|
|
|
|
<para><literal>ARGS</literal> is a collection and can be used on its own
|
|
(means all arguments including the POST Payload), with a static
|
|
parameter (matches arguments with that name), or with a regular
|
|
expression (matches all arguments with name that matches the regular
|
|
expression). To look at only the query string or body arguments, see the
|
|
<literal>ARGS_GET</literal> and <literal>ARGS_POST</literal>
|
|
collections.</para>
|
|
|
|
<para>Some variables are actually collections, which are expanded into
|
|
more variables at runtime. The following example will examine all
|
|
request arguments:<programlisting format="linespecific">SecRule ARGS dirty</programlisting>
|
|
Sometimes, however, you will want to look only at parts of a collection.
|
|
This can be achieved with the help of the <emphasis>selection
|
|
operator</emphasis>(colon). The following example will only look at the
|
|
arguments named<literal moreinfo="none"> p</literal> (do note that, in
|
|
general, requests can contain multiple arguments with the same name):
|
|
<programlisting format="linespecific">SecRule ARGS:p dirty</programlisting>
|
|
It is also possible to specify exclusions. The following will examine
|
|
all request arguments for the word<emphasis> dirty</emphasis>, except
|
|
the ones named <literal moreinfo="none">z</literal> (again, there can be
|
|
zero or more arguments named<literal moreinfo="none"> z</literal>):
|
|
<programlisting format="linespecific">SecRule ARGS|!ARGS:z dirty</programlisting>
|
|
There is a special operator that allows you to count how many variables
|
|
there are in a collection. The following rule will trigger if there is
|
|
more than zero arguments in the request (ignore the second parameter for
|
|
the time being): <programlisting format="linespecific">SecRule &ARGS !^0$</programlisting>
|
|
And sometimes you need to look at an array of parameters, each with a
|
|
slightly different name. In this case you can specify a regular
|
|
expression in the selection operator itself. The following rule will
|
|
look into all arguments whose names begin with <literal
|
|
moreinfo="none">id_</literal>: <programlisting format="linespecific">SecRule ARGS:/^id_/ dirty</programlisting></para>
|
|
|
|
<note>
|
|
<para>Using <literal>ARGS:p</literal> will not result in any
|
|
invocations against the operator if argument p does not exist.</para>
|
|
|
|
<para>In ModSecurity 1.X, the <literal>ARGS</literal> variable stood
|
|
for <literal>QUERY_STRING</literal> + <literal>POST_PAYLOAD</literal>,
|
|
whereas now it expands to to individual variables.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS_COMBINED_SIZE</literal></title>
|
|
|
|
<para>This variable allows you to set more targeted evaluations on the
|
|
total size of the Arguments as compared with normal Apache LimitRequest
|
|
directives. For example, you could create a rule to ensure that the
|
|
total size of the argument data is below a certain threshold (to help
|
|
prevent buffer overflow issues). Example: Block request if the size of
|
|
the arguments is above 25 characters.</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_FILENAME "^/cgi-bin/login\.php$" "chain,log,deny,phase:2"
|
|
SecRule <emphasis role="bold">ARGS_COMBINED_SIZE</emphasis> "@gt 25"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS_NAMES</literal></title>
|
|
|
|
<para>Is a collection of the argument names. You can search for specific
|
|
argument names that you want to block. In a positive policy scenario,
|
|
you can also whitelist (using an inverted rule with the ! character)
|
|
only authorized argument names. Example: This example rule will only
|
|
allow 2 argument names - p and a. If any other argument names are
|
|
injected, it will be blocked.</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_FILENAME "/index.php" "chain,log,deny,status:403,phase:2"
|
|
SecRule<emphasis role="bold"> ARGS_NAMES</emphasis> "!^(p|a)$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS_GET</literal></title>
|
|
|
|
<para><literal>ARGS_GET</literal> is similar to <literal>ARGS</literal>,
|
|
but only contains arguments from the query string.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS_GET_NAMES</literal></title>
|
|
|
|
<para><literal>ARGS_GET_NAMES</literal> is similar to
|
|
<literal>ARGS_NAMES</literal>, but only contains argument names from the
|
|
query string.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS_POST</literal></title>
|
|
|
|
<para><literal>ARGS_POST</literal> is similar to
|
|
<literal>ARGS</literal>, but only contains arguments from the POST
|
|
body.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ARGS_POST_NAMES</literal></title>
|
|
|
|
<para><literal>ARGS_POST_NAMES</literal> is similar to
|
|
<literal>ARGS_NAMES</literal>, but only contains argument names from the
|
|
POST body.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">AUTH_TYPE</literal></title>
|
|
|
|
<para>This variable holds the authentication method used to validate a
|
|
user. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">AUTH_TYPE</emphasis> "basic" log,deny,status:403,phase:1,t:lowercase</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This data will not be available in a proxy-mode deployment as the
|
|
authentication is not local. In a proxy-mode deployment, you would need
|
|
to inpect the <literal>REQUEST_HEADERS:Authorization</literal>
|
|
header.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">ENV</literal></title>
|
|
|
|
<para>Collection, requires a single parameter (after a colon character).
|
|
The ENV variable is set with setenv and does not give access to the CGI
|
|
environment variables. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_FILENAME "printenv" pass,<emphasis
|
|
role="bold">setenv:tag=suspicious</emphasis>
|
|
SecRule <emphasis role="bold">ENV:tag</emphasis> "suspicious"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">FILES</literal></title>
|
|
|
|
<para>Collection. Contains a collection of original file names (as they
|
|
were called on the remote user's file system). Note: only available if
|
|
files were extracted from the request body. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> FILES</emphasis> "\.conf$" log,deny,status:403,phase:2</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">FILES_COMBINED_SIZE</literal></title>
|
|
|
|
<para>Single value. Total size of the uploaded files. Note: only
|
|
available if files were extracted from the request body. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">FILES_COMBINED_SIZE</emphasis> "@gt 1000" log,deny,status:403,phase:2</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">FILES_NAMES</literal></title>
|
|
|
|
<para>Collection w/o parameter. Contains a list of form fields that were
|
|
used for file upload. Note: only available if files were extracted from
|
|
the request body. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> FILES_NAMES</emphasis> "^upfile$" log,deny,status:403,phase:2</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">FILES_SIZES</literal></title>
|
|
|
|
<para>Collection. Contains a list of file sizes. Useful for implementing
|
|
a size limitation on individual uploaded files. Note: only available if
|
|
files were extracted from the request body. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">FILES_SIZES</emphasis> "@gt 100" log,deny,status:403,phase:2</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">FILES_TMPNAMES</literal></title>
|
|
|
|
<para>Collection. Contains a collection of temporary files' names on the
|
|
disk. Useful when used together with <literal
|
|
moreinfo="none">@inspectFile.</literal> Note: only available if files
|
|
were extracted from the request body. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">FILES_TMPNAMES</emphasis> "@inspectFile /path/to/inspect_script.pl"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">GEO</literal></title>
|
|
|
|
<para><literal>GEO</literal> is a collection populated by the <literal
|
|
moreinfo="none">@geoLookups</literal> operator. It can be used to match
|
|
geographical fields looked up by an IP address or hostname.</para>
|
|
|
|
<para>Available since 2.2.0.</para>
|
|
|
|
<para>Fields:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis role="bold">COUNTRY_CODE:</emphasis> Two character
|
|
country code. EX: US, UK, etc.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">COUNTRY_CODE3:</emphasis> Up to three
|
|
character country code.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">COUNTRY_NAME:</emphasis> The full
|
|
country name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">COUNTRY_CONTINENT:</emphasis> The teo
|
|
character continent that the country is located. EX: EU</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">REGION:</emphasis> The two character
|
|
region. For US, this is state. For Canada, providence, etc.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">CITY:</emphasis> The city name.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">POSTAL_CODE:</emphasis> The postal
|
|
code.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">LATITUDE:</emphasis> The
|
|
latitude.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">LONGITUDE:</emphasis> The
|
|
longitude.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">DMA_CODE:</emphasis> The metropoliton
|
|
area code. (US only)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis role="bold">AREA_CODE:</emphasis> The phone system
|
|
area code. (US only)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REMOTE_ADDR "<emphasis
|
|
role="bold">@geoLookup</emphasis>" chain,drop,msg:'Non-UK IP address'
|
|
SecRule GEO:COUNTRY_CODE "!@streq UK"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">HIGHEST_SEVERITY</literal></title>
|
|
|
|
<para>This variable holds the highest severity of any rules that have
|
|
matched so far. Severities are numeric values and thus can be used with
|
|
comparison operators such as <literal moreinfo="none">@lt</literal>,
|
|
etc.</para>
|
|
|
|
<note>
|
|
<para>Higher severities have a lower numeric value.</para>
|
|
|
|
<para>A value of 255 indicates no severity has been set.</para>
|
|
</note>
|
|
|
|
<programlisting format="linespecific">SecRule HIGHEST_SEVERITY "@le 2" "phase:2,deny,status:500,msg:'severity %{HIGHEST_SEVERITY}'"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">MODSEC_BUILD</literal></title>
|
|
|
|
<para>This variable holds the ModSecurity build number. This variable is
|
|
intended to be used to check the build number prior to using a feature
|
|
that is available only in a certain build. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">MODSEC_BUILD</emphasis> "!@ge 02050102" skip:1
|
|
SecRule ARGS "@pm some key words" deny,status:500</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">PATH_INFO</literal></title>
|
|
|
|
<para>Besides passing query information to a script/handler, you can
|
|
also pass additional data, known as extra path information, as part of
|
|
the URL. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> PATH_INFO</emphasis> "^/(bin|etc|sbin|opt|usr)"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">QUERY_STRING</literal></title>
|
|
|
|
<para>This variable holds form data passed to the script/handler by
|
|
appending data after a question mark. Warning: Not URL-decoded.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">QUERY_STRING</emphasis> "attack"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REMOTE_ADDR</literal></title>
|
|
|
|
<para>This variable holds the IP address of the remote client.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REMOTE_ADDR</emphasis> "^192\.168\.1\.101$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REMOTE_HOST</literal></title>
|
|
|
|
<para>If HostnameLookUps are set to On, then this variable will hold the
|
|
DNS resolved remote host name. If it is set to Off, then it will hold
|
|
the remote IP address. Possible uses for this variable would be to deny
|
|
known bad client hosts or network blocks, or conversely, to allow in
|
|
authorized hosts. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REMOTE_HOST</emphasis> "\.evil\.network\org$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REMOTE_PORT</literal></title>
|
|
|
|
<para>This variable holds information on the source port that the client
|
|
used when initiating the connection to our web server. Example: in this
|
|
example, we are evaluating to see if the <literal>REMOTE_PORT</literal>
|
|
is less than 1024, which would indicate that the user is a privileged
|
|
user (root).</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REMOTE_PORT</emphasis> "@lt 1024" phase:1,log,pass,setenv:remote_port=privileged</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REMOTE_USER</literal></title>
|
|
|
|
<para>This variable holds the username of the authenticated user. If
|
|
there are no password (basic|digest) access controls in place, then this
|
|
variable will be empty. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REMOTE_USER</emphasis> "admin"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This data will not be available in a proxy-mode deployment as the
|
|
authentication is not local.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQBODY_PROCESSOR</literal></title>
|
|
|
|
<para>Built-in processors are <literal
|
|
moreinfo="none">URLENCODED</literal>,<literal moreinfo="none">
|
|
MULTIPART</literal>, and <literal moreinfo="none">XML</literal>.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> REQBODY_PROCESSOR</emphasis> "^XML$ chain
|
|
SecRule XML "@validateDTD /opt/apache-frontend/conf/xml.dtd"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal
|
|
moreinfo="none">REQBODY_PROCESSOR_ERROR</literal></title>
|
|
|
|
<para>Possible values are 0 (no error) or 1 (error). This variable will
|
|
be set by request body processors (typically the
|
|
<classname>multipart/request-data</classname> parser or the XML parser)
|
|
when they fail to properly parse a request payload.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> REQBODY_PROCESSOR_ERROR</emphasis> "@eq 1" deny,phase:2</programlisting>
|
|
|
|
<note>
|
|
<para>Your policies <emphasis>must</emphasis> have a rule to check
|
|
REQBODY_PROCESSOR_ERROR at the beginning of phase 2. Failure to do so
|
|
will leave the door open for impedance mismatch attacks. It is
|
|
possible, for example, that a payload that cannot be parsed by
|
|
ModSecurity can be successfully parsed by more tolerant parser
|
|
operating in the application. If your policy dictates blocking then
|
|
you should reject the request if error is detected. When operating in
|
|
detection-only mode your rule should alert with high severity when
|
|
request body processing fails.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal
|
|
moreinfo="none">REQBODY_PROCESSOR_ERROR_MSG</literal></title>
|
|
|
|
<para>Empty, or contains the error message from the processor.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> REQBODY_PROCESSOR_ERROR_MSG</emphasis> "failed to parse" t:lowercase</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_BASENAME</literal></title>
|
|
|
|
<para>This variable holds just the filename part of
|
|
<literal>REQUEST_FILENAME</literal> (e.g. index.php). Warning: not
|
|
urlDecoded. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_BASENAME</emphasis> "^login\.php$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_BODY</literal></title>
|
|
|
|
<para>This variable holds the data in the request body (including
|
|
POST_PAYLOAD data). REQUEST_BODY should be used if the original order of
|
|
the arguements is important (ARGS should be used in all other cases).
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_BODY</emphasis> "^username=\w{25,}\&password=\w{25,}\&Submit\=login$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is only available if the content type is
|
|
application/x-www-form-urlencoded.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_COOKIES</literal></title>
|
|
|
|
<para>This variable is a collection of all of the cookie data. Example:
|
|
the following example is using the Ampersand special operator to count
|
|
how many variables are in the collection. In this rule, it would trigger
|
|
if the request does not include any Cookie headers.</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> &REQUEST_COOKIES</emphasis> "@eq 0"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_COOKIES_NAMES</literal></title>
|
|
|
|
<para>This variable is a collection of the cookie names in the request
|
|
headers. Example: the following rule will trigger if the JSESSIONID
|
|
cookie is not present.</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> &REQUEST_COOKIES_NAMES:JSESSIONID</emphasis> "@eq 0"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_FILENAME</literal></title>
|
|
|
|
<para>This variable holds the relative REQUEST_URI minus the
|
|
QUERY_STRING part (e.g. /index.php). Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_FILENAME</emphasis> "^/cgi-bin/login\.php$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_HEADERS</literal></title>
|
|
|
|
<para>This variable can be used as either a collection of all of the
|
|
Request Headers or can be used to specify indivudual headers (by using
|
|
REQUEST_HEADERS<emphasis>:Header-Name</emphasis>). Example: the first
|
|
example uses REQUEST_HEADERS as a collection and is applying the
|
|
validateUrlEncoding operator against all headers.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_HEADERS</emphasis> "@validateUrlEncoding"</programlisting>
|
|
|
|
<para>Example: the second example is targeting only the Host
|
|
header.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_HEADERS:Host</emphasis> "^[\d\.]+$" \
|
|
"deny,log,status:400,msg:'Host header is a numeric IP address'"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_HEADERS_NAMES</literal></title>
|
|
|
|
<para>This variable is a collection of the names of all of the Request
|
|
Headers. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_HEADERS_NAMES</emphasis> "^x-forwarded-for" \
|
|
"log,deny,status:403,t:lowercase,msg:'Proxy Server Used'"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_LINE</literal></title>
|
|
|
|
<para>This variable holds the complete request line sent to the server
|
|
(including the REQUEST_METHOD and HTTP version data). Example: this
|
|
example rule will trigger if the request method is something other than
|
|
GET, HEAD, POST or if the HTTP is something other than HTTP/0.9, 1.0 or
|
|
1.1.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_LINE</emphasis> "!(^((?:(?:pos|ge)t|head))|http/(0\.9|1\.0|1\.1)$)"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Due to the default action transformation function lowercase, the
|
|
regex strings should be in lowercase as well unless the t:none
|
|
transformation function is specified for this particular rule.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_METHOD</literal></title>
|
|
|
|
<para>This variable holds the Request Method used by the client.
|
|
Example: the following example will trigger if the Request Method is
|
|
either CONNECT or TRACE.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_METHOD</emphasis> "^((?:connect|trace))$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Due to the default action transformation function lowercase, the
|
|
regex strings should be in lowercase as well unless the t:none
|
|
transformation function is specified for this particular rule.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_PROTOCOL</literal></title>
|
|
|
|
<para>This variable holds the Request Protocol Version information.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_PROTOCOL</emphasis> "!^http/(0\.9|1\.0|1\.1)$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Due to the default action transformation function lowercase, the
|
|
regex strings should be in lowercase as well unless the t:none
|
|
transformation function is specified for this particular rule.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_URI</literal></title>
|
|
|
|
<para>This variable holds the full URL including the QUERY_STRING data
|
|
(e.g. /index.php?p=X), however it will never contain a domain name, even
|
|
if it was provided on the request line. Warning: not urlDecoded. It also
|
|
does not include either the REQUEST_METHOD or the HTTP version info.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">REQUEST_URI</emphasis> "attack"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_URI_RAW</literal></title>
|
|
|
|
<para>Same as REQUEST_URI but will contain the domain name if it was
|
|
provided on the request line (e.g.
|
|
http://www.example.com/index.php?p=X). Warning: not urlDecoded.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> REQUEST_URI_RAW</emphasis> "http:/"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">RESPONSE_BODY</literal></title>
|
|
|
|
<para>This variable holds the data for the response payload.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> RESPONSE_BODY</emphasis> "ODBC Error Code"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>RESPONSE_CONTENT_LENGTH</literal></title>
|
|
|
|
<para>Response body length in bytes. Can be available starting with
|
|
phase 3 but it does not have to be (as the length of response body is
|
|
not always known in advance.) If the size is not known this variable
|
|
will contain a zero. If <literal>RESPONSE_CONTENT_LENGTH</literal>
|
|
contains a zero in phase 5 that means the actual size of the response
|
|
body was 0.</para>
|
|
|
|
<para>The value of this variable can change between phases if the body
|
|
is modified. For example, in embedded mode
|
|
<literal>mod_deflate</literal> can compress the response body between
|
|
phases 4 and 5.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>RESPONSE_CONTENT_TYPE</literal></title>
|
|
|
|
<para>Response content type. Only available starting with phase
|
|
3.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">RESPONSE_HEADERS</literal></title>
|
|
|
|
<para>This variable is similar to the REQUEST_HEADERS variable and can
|
|
be used in the same manner. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> RESPONSE_HEADERS</emphasis><emphasis
|
|
role="bold">:X-Cache</emphasis> "MISS"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable may not have access to some headers when running in
|
|
embedded-mode. Headers such as Server, Date, Connection and Content-Type
|
|
are added during a later Apache hook just prior to sending the data to
|
|
the client. This data should be available, however, either during
|
|
ModSecurity phase:5 (logging) or when running in proxy-mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">RESPONSE_HEADERS_NAMES</literal></title>
|
|
|
|
<para>This variable is a collection of the response header names.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">RESPONSE_HEADERS_NAMES</emphasis> "Set-Cookie"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Same limitations as RESPONSE_HEADERS with regards to access to
|
|
some headers in embedded-mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">RESPONSE_PROTOCOL</literal></title>
|
|
|
|
<para>This variable holds the HTTP Response Protocol information.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">RESPONSE_PROTOCOL</emphasis> "^HTTP\/0\.9"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">RESPONSE_STATUS</literal></title>
|
|
|
|
<para>This variable holds the HTTP Response Status Code generated by
|
|
Apache. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">RESPONSE_STATUS</emphasis> "^[45]"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This directive may not work as expected in embedded-mode as Apache
|
|
handles many of the stock response codes (404, 401, etc...) earlier in
|
|
Phase 2. This variable should work as expected in a proxy-mode
|
|
deployment.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">RULE</literal></title>
|
|
|
|
<para>This variable provides access to the <literal
|
|
moreinfo="none">id</literal>, <literal moreinfo="none">rev</literal>,
|
|
<literal moreinfo="none">severity</literal>, <literal
|
|
moreinfo="none">logdata</literal>, and <literal
|
|
moreinfo="none">msg</literal> fields of the rule that triggered the
|
|
action. Only available for expansion in action strings (e.g.<literal
|
|
moreinfo="none">setvar:tx.varname=%{rule.id}</literal>). Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS:Host "@eq 0" "log,deny,setvar:tx.varname=<emphasis
|
|
role="bold">%{rule.id}</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_BASENAME</literal></title>
|
|
|
|
<para>This variable holds just the local filename part of
|
|
SCRIPT_FILENAME. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SCRIPT_BASENAME</emphasis> "^login\.php$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_FILENAME</literal></title>
|
|
|
|
<para>This variable holds the full path on the server to the requested
|
|
script. (e.g. SCRIPT_NAME plus the server path). Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SCRIPT_FILENAME</emphasis> "^/usr/local/apache/cgi-bin/login\.php$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_GID</literal></title>
|
|
|
|
<para>This variable holds the groupid (numerical value) of the group
|
|
owner of the script. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SCRIPT_GID</emphasis> "!^46$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_GROUPNAME</literal></title>
|
|
|
|
<para>This variable holds the group name of the group owner of the
|
|
script. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> SCRIPT_GROUPNAME</emphasis> "!^apache$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_MODE</literal></title>
|
|
|
|
<para>This variable holds the script's permissions mode data (numerical
|
|
- 1=execute, 2=write, 4=read and 7=read/write/execute). Example: will
|
|
trigger if the script has the WRITE permissions set.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SCRIPT_MODE</emphasis> "^(2|3|6|7)$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_UID</literal></title>
|
|
|
|
<para>This variable holds the userid (numerical value) of the owner of
|
|
the script. Example: the example rule below will trigger if the UID is
|
|
not 46 (the Apache user).</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> SCRIPT_UID</emphasis> "!^46$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SCRIPT_USERNAME</literal></title>
|
|
|
|
<para>This variable holds the username of the owner of the script.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SCRIPT_USERNAME</emphasis> "!^apache$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This variable is not available in proxy mode.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SERVER_ADDR</literal></title>
|
|
|
|
<para>This variable contains the IP address of the server.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> SERVER_ADDR</emphasis> "^192\.168\.1\.100$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SERVER_NAME</literal></title>
|
|
|
|
<para>This variable contains the server's hostname or IP address.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SERVER_NAME</emphasis> "hostname\.com$"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This data is taken from the Host header submitted in the client
|
|
request.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SERVER_PORT</literal></title>
|
|
|
|
<para>This variable contains the local port that the web server is
|
|
listening on. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SERVER_PORT</emphasis> "^80$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SESSION</literal></title>
|
|
|
|
<para>This variable is a collection, available only after <literal
|
|
moreinfo="none">setsid</literal> is executed. Example: the following
|
|
example shows how to initialize a SESSION collection with setsid, how to
|
|
use setvar to increase the session.score values, how to set the
|
|
session.blocked variable and finally how to deny the connection based on
|
|
the session:blocked value.</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
|
|
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
|
|
SecRule REQUEST_URI "^/cgi-bin/finger$" "pass,log,setvar:<emphasis role="bold">session.score</emphasis>=+10"
|
|
SecRule<emphasis role="bold"> SESSION:SCORE</emphasis> "@gt 50" "pass,log,setvar:<emphasis
|
|
role="bold">session.blocked</emphasis>=1"
|
|
SecRule<emphasis role="bold"> SESSION:BLOCKED</emphasis> "@eq 1" "log,deny,status:403"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">SESSIONID</literal></title>
|
|
|
|
<para>This variable is the value set with <literal
|
|
moreinfo="none">setsid</literal>. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">SESSIONID</emphasis> !^$ chain,nolog,pass
|
|
SecRule REQUEST_COOKIES:PHPSESSID !^$
|
|
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME</literal></title>
|
|
|
|
<para>This variable holds a formatted string representing the time
|
|
(hour:minute:second). Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> TIME</emphasis> "^(([1](8|9))|([2](0|1|2|3))):\d{2}:\d{2}$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_DAY</literal></title>
|
|
|
|
<para>This variable holds the current date (1-31). Example: this rule
|
|
would trigger anytime between the 10th and 20th days of the
|
|
month.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">TIME_DAY</emphasis> "^(([1](0|1|2|3|4|5|6|7|8|9))|20)$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_EPOCH</literal></title>
|
|
|
|
<para>This variable holds the time in seconds since 1970.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">TIME_EPOCH</emphasis> "@gt 1000"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_HOUR</literal></title>
|
|
|
|
<para>This variable holds the current hour (0-23). Example: this rule
|
|
would trigger during "off hours".</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> TIME_HOUR</emphasis> "^(0|1|2|3|4|5|6|[1](8|9)|[2](0|1|2|3))$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_MIN</literal></title>
|
|
|
|
<para>This variable holds the current minute (0-59). Example: this rule
|
|
would trigger during the last half hour of every hour.</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">TIME_MIN</emphasis> "^(3|4|5)"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_MON</literal></title>
|
|
|
|
<para>This variable holds the current month (0-11). Example: this rule
|
|
would match if the month was either November (10) or December
|
|
(11).</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> TIME_MON</emphasis> "^1"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_SEC</literal></title>
|
|
|
|
<para>This variable holds the current second count (0-59).
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">TIME_SEC</emphasis> "@gt 30"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_WDAY</literal></title>
|
|
|
|
<para>This variable holds the current weekday (0-6). Example: this rule
|
|
would trigger only on week-ends (Saturday and Sunday).</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">TIME_WDAY</emphasis> "^(0|6)$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TIME_YEAR</literal></title>
|
|
|
|
<para>This variable holds the current four-digit year data.
|
|
Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule <emphasis role="bold">TIME_YEAR</emphasis> "^2006$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">TX</literal></title>
|
|
|
|
<para>Transaction Collection. This is used to store pieces of data,
|
|
create a transaction anomaly score, and so on. Transaction variables are
|
|
set for 1 request/response cycle. The scoring and evaluation will not
|
|
last past the current request/response process. Example: In this
|
|
example, we are using setvar to increase the tx.score value by 5 points.
|
|
We then have a follow-up run that will evaluate the transactional score
|
|
this this request and then it will decided whether or not to allow/deny
|
|
the request through.</para>
|
|
|
|
<programlisting format="linespecific">SecRule WEBSERVER_ERROR_LOG "does not exist" "phase:5,pass,<emphasis
|
|
role="bold">setvar:tx.score=+5</emphasis>"
|
|
SecRule<emphasis role="bold"> TX:SCORE</emphasis> "@gt 20" deny,log</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">USERID</literal></title>
|
|
|
|
<para>This variable is the value set with <literal
|
|
moreinfo="none">setuid</literal>. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecAction setuid:%{REMOTE_USER},nolog
|
|
SecRule<emphasis role="bold"> USERID</emphasis> "Admin"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">WEBAPPID</literal></title>
|
|
|
|
<para>This variable is the value set with <literal
|
|
moreinfo="none">SecWebAppId</literal>. Example:</para>
|
|
|
|
<programlisting format="linespecific">SecWebAppId "WebApp1"
|
|
SecRule<emphasis role="bold"> WEBAPPID</emphasis> "WebApp1" "chain,log,deny,status:403"
|
|
SecRule REQUEST_HEADERS:Transfer-Encoding "!^$"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">WEBSERVER_ERROR_LOG</literal></title>
|
|
|
|
<para>Contains zero or more error messages produced by the web server.
|
|
Access to this variable is in phase:5 (logging). Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule<emphasis role="bold"> WEBSERVER_ERROR_LOG</emphasis> "File does not exist" "phase:5,setvar:tx.score=+5"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal moreinfo="none">XML</literal></title>
|
|
|
|
<para>Can be used standalone (as a target for validateDTD and
|
|
validateSchema) or with an XPath expression parameter (which makes it a
|
|
valid target for any function that accepts plain text). Example using
|
|
XPath:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,status:403,phase:2
|
|
SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \
|
|
phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=<emphasis
|
|
role="bold">XML</emphasis>
|
|
SecRule REQBODY_PROCESSOR "<emphasis role="bold">!^XML$</emphasis>" skip:2
|
|
SecRule <emphasis role="bold">XML:/employees/employee/name/text()</emphasis> Fred
|
|
SecRule <emphasis role="bold">XML:/xq:employees/employee/name/text()</emphasis> Fred \
|
|
xmlns:xq=http://www.example.com/employees</programlisting>
|
|
|
|
<para>The first XPath expression does not use namespaces. It would match
|
|
against payload such as this one:</para>
|
|
|
|
<programlisting><employees>
|
|
<employee>
|
|
<name>Fred Jones</name>
|
|
<address location="home">
|
|
<street>900 Aurora Ave.</street>
|
|
<city>Seattle</city>
|
|
<state>WA</state>
|
|
<zip>98115</zip>
|
|
</address>
|
|
<address location="work">
|
|
<street>2011 152nd Avenue NE</street>
|
|
<city>Redmond</city>
|
|
<state>WA</state>
|
|
<zip>98052</zip>
|
|
</address>
|
|
<phone location="work">(425)555-5665</phone>
|
|
<phone location="home">(206)555-5555</phone>
|
|
<phone location="mobile">(206)555-4321</phone>
|
|
</employee>
|
|
</employees></programlisting>
|
|
|
|
<para>The second XPath expression does use namespaces. It would match
|
|
the following payload:</para>
|
|
|
|
<programlisting><xq:employees xmlns:xq="http://www.example.com/employees">
|
|
<employee>
|
|
<name>Fred Jones</name>
|
|
<address location="home">
|
|
<street>900 Aurora Ave.</street>
|
|
<city>Seattle</city>
|
|
<state>WA</state>
|
|
<zip>98115</zip>
|
|
</address>
|
|
<address location="work">
|
|
<street>2011 152nd Avenue NE</street>
|
|
<city>Redmond</city>
|
|
<state>WA</state>
|
|
<zip>98052</zip>
|
|
</address>
|
|
<phone location="work">(425)555-5665</phone>
|
|
<phone location="home">(206)555-5555</phone>
|
|
<phone location="mobile">(206)555-4321</phone>
|
|
</employee>
|
|
</xq:employees></programlisting>
|
|
|
|
<para>Note the different namespace used in the second example.</para>
|
|
|
|
<para>To learn more about XPath we suggest the following
|
|
resources:</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para><ulink url="http://www.w3.org/TR/xpath">XPath
|
|
Standard</ulink></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink
|
|
url="http://www.zvon.org/xxl/XPathTutorial/General/examples.html">XPath
|
|
Tutorial</ulink></para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="06-transformation-functions">
|
|
<title>Transformation functions</title>
|
|
|
|
<para>When ModSecurity receives request or response information, it makes
|
|
a copy of this data and places it into memory. It is on this data in
|
|
memory that transformation functions are applied. The raw request/response
|
|
data is never altered. Transformation functions are used to transform a
|
|
variable before testing it in a rule.</para>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The default transformation function setting is - lowercase,
|
|
replaceNulls and compressWhitespace (in this order).</para>
|
|
|
|
<para>The following rule will ensure that an attacker does not use mixed
|
|
case in order to evade the ModSecurity rule:</para>
|
|
|
|
<para><programlisting format="linespecific">SecRule ARG:p "xp_cmdshell" <emphasis
|
|
role="bold">"t:lowercase"</emphasis></programlisting> multiple
|
|
tranformation actions can be used in the same rule, for example the
|
|
following rule also ensures that an attacker does not use URL encoding
|
|
(%xx encoding) for evasion. Note the order of the transformation
|
|
functions, which ensures that a URL encoded letter is first decoded and
|
|
than translated to lower case.</para>
|
|
|
|
<para><programlisting format="linespecific">SecRule ARG:p "xp_cmdshell" <emphasis
|
|
role="bold">"t:urlDecode,t:lowercase"</emphasis></programlisting></para>
|
|
|
|
<para>One can use the SetDefaultAction command to ensure the translation
|
|
occurs for every rule until the next. Note that translation actions are
|
|
additive, so if a rule explicitly list actions, the translation actions
|
|
set by SetDefaultAction are still performed.</para>
|
|
|
|
<para><programlisting format="linespecific">SecDefaultAction <emphasis
|
|
role="bold">t:urlDecode,t:lowercase</emphasis></programlisting></para>
|
|
|
|
<para>The following transformation functions are supported:</para>
|
|
|
|
<section>
|
|
<title><literal>base64Decode</literal></title>
|
|
|
|
<para>This function decoes a base64-encoded string.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>base64Encode</literal></title>
|
|
|
|
<para>This function encodes input string using base64 encoding.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>compressWhitespace</literal></title>
|
|
|
|
<para>This function is enabled by default. It converts whitespace
|
|
characters (32, \f, \t, \n, \r, \v, 160) to spaces (ASCII 32) and then
|
|
compresses multiple space characters into only one.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>escapeSeqDecode</literal></title>
|
|
|
|
<para>This function decode ANSI C escape sequences:<literal
|
|
moreinfo="none"> \a</literal>,<literal moreinfo="none"> \b</literal>,
|
|
<literal moreinfo="none">\f</literal>, <literal
|
|
moreinfo="none">\n</literal>, <literal moreinfo="none">\r</literal>,
|
|
<literal moreinfo="none">\t</literal>, <literal
|
|
moreinfo="none">\v</literal>, <literal moreinfo="none">\\</literal>,
|
|
<literal moreinfo="none">\?</literal>, <literal
|
|
moreinfo="none">\'</literal>, <literal moreinfo="none">\"</literal>,
|
|
<literal moreinfo="none">\xHH</literal> (hexadecimal), <literal
|
|
moreinfo="none">\0OOO</literal> (octal). Invalid encodings are left in
|
|
the output.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>hexDecode</literal></title>
|
|
|
|
<para>This function decodes a hex-encoded string.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>hexEncode</literal></title>
|
|
|
|
<para>This function encodes input as hex-encoded string.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>htmlEntityDecode</literal></title>
|
|
|
|
<para>This function decodes HTML entities present in input. The
|
|
following variants are supported:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">&#xHH</literal> and <literal
|
|
moreinfo="none">&#xHH;</literal> (where H is any hexadecimal
|
|
number)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">&#DDD</literal> and <literal
|
|
moreinfo="none">&#DDD;</literal> (where D is any decimal
|
|
number)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">&quot</literal> and <literal
|
|
moreinfo="none">&quot;</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">&nbsp</literal> and <literal
|
|
moreinfo="none">&nbsp;</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">&lt</literal> and <literal
|
|
moreinfo="none">&lt;</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">&gt</literal> and <literal
|
|
moreinfo="none">&gt;</literal></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>length</literal></title>
|
|
|
|
<para>This function converts the input to its numeric length (count of
|
|
characters).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>lowercase</literal></title>
|
|
|
|
<para>This function is enabled by default. It converts all charactes to
|
|
lowercase using the current C locale.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>md5</literal></title>
|
|
|
|
<para>This function calculates an MD5 hash from input.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal><literal>none</literal></literal></title>
|
|
|
|
<para>This not an actual transformation function but an instruction to
|
|
ModSecurity to remove all transformation functions associated with the
|
|
current rule and start from scratch.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>normalisePath</literal></title>
|
|
|
|
<para>This function will remove multiple slashes, self-references and
|
|
directory back-references (except when they are at the beginning of the
|
|
path).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>normalisePathWin</literal></title>
|
|
|
|
<para>Same as normalisePath, but will first convert backslash characters
|
|
to forward slashes.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>removeNulls</literal></title>
|
|
|
|
<para>This function removes NULL bytes from input.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>removeWhitespace</literal></title>
|
|
|
|
<para>This function removes all whitespace characters.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>replaceComments</literal></title>
|
|
|
|
<para>This function replaces each occurence of a C-style comments
|
|
(<literal moreinfo="none">/* ... */</literal>) with a single space
|
|
(multiple consecutive occurences of a space will not be compressed).
|
|
Unterminated comments will too be replaced with a space (ASCII 32).
|
|
However, a standalone termination of a comment (<literal
|
|
moreinfo="none">*/</literal>) will not be acted upon.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>replaceNulls</literal></title>
|
|
|
|
<para>This function is enabled by default. It replaces NULL bytes in
|
|
input with spaces (ASCII 32).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>urlDecode</literal></title>
|
|
|
|
<para>This function decodes an URL-encoded input string. Invalid
|
|
encodings (i.e. the ones that use non-hexadecimal characters, or the
|
|
ones that are at the end of string and have one or two characters
|
|
missing) will not be converted. If you want to detect invalid encodings
|
|
use the <literal moreinfo="none">@validateUrlEncoding</literal>
|
|
operator. The transformational function should not be used against
|
|
variables that have already been URL-decoded unless it is your intention
|
|
to perform URL decoding twice!</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>urlDecodeUni</literal></title>
|
|
|
|
<para>In addition to decoding %xx like <literal
|
|
moreinfo="none">urlDecode, urlDecodeUni</literal> also decodes <literal
|
|
moreinfo="none">%uXXXX</literal> encoding. If the code is in the range
|
|
of FF01-FF5E (the full width ASCII codes), then the higher byte is used
|
|
to detect and adjust the lower byte. Otherwise, only the lower byte will
|
|
be used and the higher byte zeroed.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>urlEncode</literal></title>
|
|
|
|
<para>This function encodes input using URL encoding.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>sha1</literal></title>
|
|
|
|
<para>This function calculates a SHA1 hash from input.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>trimLeft</literal></title>
|
|
|
|
<para>This function removes whitespace from the left side of
|
|
input.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>trimRight</literal></title>
|
|
|
|
<para>This function removes whitespace from the right side of
|
|
input.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>trim</literal></title>
|
|
|
|
<para>This function removes whitespace from both the left and right
|
|
sides of input.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="07-actions">
|
|
<title>Actions</title>
|
|
|
|
<para>Each action belongs to one of five groups:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para><emphasis>Disruptive actions</emphasis> - are those actions
|
|
where ModSecurity will intercept the data. They can only appear in the
|
|
first rule in a chain.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Non-disruptive actions</emphasis> - can appear
|
|
anywhere.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Flow actions</emphasis> - can appear only in the first
|
|
rule in a chain.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Meta-data actions</emphasis>(<literal
|
|
moreinfo="none">id</literal>,<literal moreinfo="none">
|
|
rev</literal>,<literal moreinfo="none"> severity</literal>,<literal
|
|
moreinfo="none"> msg</literal>) - can only appear in the first rule in
|
|
a chain.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Data actions</emphasis> - can appear anywhere; these
|
|
actions are completely passive and only serve to carry data used by
|
|
other actions.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<section>
|
|
<title><literal>allow</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Stops processing on
|
|
a successful match and allows transaction to proceed.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,<emphasis
|
|
role="bold">allow</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The allow action only applies to the current processing phase. If
|
|
your intent is to explicitly allow a request, then you should use the
|
|
"ctl" action to turn the ruleEngine off -<literal moreinfo="none">
|
|
ctl:ruleEngine=Off</literal>.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>append (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Appends text given
|
|
as parameter to the end of response body. For this action to work
|
|
content injection must be enabled by setting
|
|
<literal>SecContentInjection</literal> to <literal>On</literal>. 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).</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para><emphasis role="bold">Processing Phases:</emphasis> 3 and
|
|
4.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting>SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,pass,<emphasis
|
|
role="bold">append:'<hr>Footer'</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>auditlog</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Marks the
|
|
transaction for logging in the audit log.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REMOTE_ADDR "^192\.168\.1\.100$" <emphasis
|
|
role="bold">auditlog</emphasis>,phase:1,allow</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The auditlog action is now explicit if log is already
|
|
specified.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>capture</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> 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.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_BODY "^username=(\w{25,})" phase:2,<emphasis
|
|
role="bold">capture</emphasis>,t:none,chain
|
|
SecRule TX:1 "(?:(?:a(dmin|nonymous)))"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The 0 data captures the entire REGEX match and 1 captures the data
|
|
in the first parantheses, etc...</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>chain</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Chains the rule
|
|
where the action is placed with the rule that immediately follows it.
|
|
The result is called a<emphasis> rule chain</emphasis>. 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.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Flow</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific"># Refuse to accept POST requests that do
|
|
# not specify request body length
|
|
SecRule REQUEST_METHOD ^POST$<emphasis role="bold"> chain</emphasis>
|
|
SecRule REQUEST_HEADER:Content-Length ^$</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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)
|
|
and skip actions can only be specified on by the chain starter
|
|
rule.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>ctl</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> The ctl action
|
|
allows configuration options to be updated for the transaction.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific"># Parse requests with Content-Type "text/xml" as XML
|
|
SecRule REQUEST_CONTENT_TYPE ^text/xml nolog,pass,<emphasis role="bold">ctl:requestBodyProcessor=XML</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The following configuration options are supported:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para><literal moreinfo="none">auditEngine</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">auditLogParts</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">debugLogLevel</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">requestBodyAccess</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">requestBodyLimit</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">requestBodyProcessor</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">responseBodyAccess</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">responseBodyLimit</literal></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">ruleEngine</literal></para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>With the exception of<literal moreinfo="none">
|
|
requestBodyProcessor</literal>, each configuration option corresponds to
|
|
one configuration directive and the usage is identical.</para>
|
|
|
|
<para>The requestBodyProcessor option allows you to configure the
|
|
request body processor. By default ModSecurity will use the <literal
|
|
moreinfo="none">URLENCODED</literal> and<literal moreinfo="none">
|
|
MULTIPART</literal> processors to process an <literal
|
|
moreinfo="none">application/x-www-form-urlencoded</literal> and a
|
|
<literal moreinfo="none">multipart/form-data</literal> body,
|
|
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<literal moreinfo="none"> REQUEST_HEADERS</literal>
|
|
processing phase. After the request body was processed as XML you will
|
|
be able to use the XML-related features to inspect it.</para>
|
|
|
|
<para>Request body processors will not interrupt a transaction if an
|
|
error occurs during parsing. Instead they will set variables<literal
|
|
moreinfo="none"> REQBODY_PROCESSOR_ERROR</literal> and<literal
|
|
moreinfo="none"> REQBODY_PROCESSOR_ERROR_MSG</literal>. These variables
|
|
should be inspected in the <literal
|
|
moreinfo="none">REQUEST_BODY</literal> phase and an appropriate action
|
|
taken.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>deny</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Stops rule
|
|
processing and intercepts transaction.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "nikto" log,<emphasis
|
|
role="bold">deny</emphasis>,msg:'Nikto Scanners Identified"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>deprecatevar</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Decrement counter
|
|
based on its age.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example: The following example will decrement the counter by 60
|
|
every 300 seconds.</para>
|
|
|
|
<programlisting format="linespecific">SecAction deprecatevar:session.score=60/300</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Counter values are always positive, meaning the value will never
|
|
go below zero.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>drop</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Immediately initiate
|
|
a "connection close" action to tear down the TCP connection by sending a
|
|
FIN packet.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>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.</para>
|
|
|
|
<programlisting format="linespecific">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,<emphasis role="bold">drop</emphasis>,phase:1,msg:'Possible Brute Force Attack"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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"</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>exec</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Executes an external
|
|
script/binary supplied as parameter.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_URI "^/cgi-bin/script\.pl" \
|
|
"log,<emphasis role="bold">exec:/usr/local/apache/bin/test.sh</emphasis>,phase:1"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This directive does not effect a primary action if it exists. This
|
|
action will always call script with no parameters, but providing all
|
|
information in the environment. All the usual CGI environment variables
|
|
will be there. You can have one binary executed per filter match.
|
|
Execution will add the header mod_security-executed to the list of
|
|
request headers. 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 multithreaded operation. The script
|
|
you execute must write something (anything) to stdout. If it doesn't
|
|
ModSecurity will assume execution didn't work.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>expirevar</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Configurescollection
|
|
variable to expire after the given time in seconds.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_COOKIES:JSESSIONID "!^$" nolog,phase:1,pass,chain
|
|
SecAction setsid:%{REQUEST_COOKIES:JSESSIONID}
|
|
SecRule REQUEST_URI "^/cgi-bin/script\.pl" \
|
|
"log,allow,setvar:session.suspicious=1,<emphasis role="bold">expirevar:session.suspicious=3600</emphasis>,phase:1"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>You should use expirevar actions at the same time that you use
|
|
setvar actions in order to keep the indended 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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>id</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Assigns a unique ID
|
|
to the rule or chain.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Metadata</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS:Host "@eq 0" \
|
|
"log,<emphasis role="bold">id:60008</emphasis>,severity:2,msg:'Request Missing a Host Header'"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>These are the reserved ranges:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>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.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>100,000-199,999; reserved for internal use of the engine, to
|
|
assign to rules that do not have explicit IDs.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>200,000-299,999; reserved for rules published at
|
|
modsecurity.org.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>300,000-399,999; reserved for rules published at
|
|
gotroot.com.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>400,000-419,999; unused (available for reservation).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>420,000-429,999; reserved for <ulink type=""
|
|
url="http://projects.otaku42.de/wiki/ScallyWhack">ScallyWhack</ulink>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>430,000-899,999; unused (available for reservation).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>900,000-999,999; reserved for the <ulink
|
|
url="http://www.modsecurity.org/projects/rules/">Core Rules</ulink>
|
|
project.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>1,000,000 and above; unused (available for
|
|
reservation).</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>initcol</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Initialises a named
|
|
persistent collection, either by loading data from storage or by
|
|
creating a new collection in memory.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example: The following example initiates IP address
|
|
tracking.</para>
|
|
|
|
<programlisting format="linespecific">SecAction<emphasis role="bold"> initcol:ip=%{REMOTE_ADDR}</emphasis>,nolog</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Every collection contains several built-in variables that are
|
|
read-only:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para><literal moreinfo="none">CREATE_TIME</literal> - date/time of
|
|
the creation of the collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">KEY</literal> - the value of the
|
|
initcol variable (the client's IP address in the example).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">LAST_UPDATE_TIME</literal> -
|
|
date/time of the last update to the collection.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">TIMEOUT</literal> - date/time in
|
|
seconds when the collection will be updated on disk from memory (if
|
|
no other updates occur).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">UPDATE_COUNTER</literal> - how many
|
|
times the collection has been updated since creation.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal moreinfo="none">UPDATE_RATE</literal> - is the
|
|
average rate updates per minute since creation.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>Collections are loaded into memory when the initcol action is
|
|
encountered. The collection in storage will be updated (and the
|
|
appropriate counters increased) <emphasis>only</emphasis> if it was
|
|
changed during transaction processing.</para>
|
|
|
|
<note>
|
|
<para>To create a collection to hold session variables (<literal
|
|
moreinfo="none">SESSION</literal>) use action <literal
|
|
moreinfo="none">setsid</literal>. To create a collection to hold user
|
|
variables (<literal moreinfo="none">USER</literal>) use action
|
|
<literal moreinfo="none">setuid</literal>.</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>At this time it is only possible to have three
|
|
collections:<literal moreinfo="none"> IP</literal>,<literal
|
|
moreinfo="none"> SESSION</literal>, and <literal
|
|
moreinfo="none">USER</literal>.</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>Please note that ModSecurity does not implement atomic updates
|
|
of persistent variables at this time. Variables are read from storage
|
|
whenever <literal>initcol</literal> is encountered in the rules and
|
|
persisted at the end of request processing. On busy servers requests
|
|
often run in parallel, leading to situations where one request
|
|
overwrites the changes made by another request. We anticipate
|
|
implementing atomic updates of counter values in a future
|
|
version.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>log</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Indicates that a
|
|
successful match of the rule needs to be logged.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecAction initcol:ip=%{REMOTE_ADDR},<emphasis
|
|
role="bold">log</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This action will log matches to the Apache error log file and the
|
|
ModSecurity audit log.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>logdata</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Allows logging a
|
|
data fragment.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Metadata</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &ARGS:p "@eq 0" "log,<emphasis
|
|
role="bold">logdata:'%{TX.0}'"</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>msg</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Assigns a custom
|
|
message to the rule or chain.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Metadata</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS:Host "@eq 0" \
|
|
"log,id:60008<emphasis role="bold">,</emphasis>severity:2,<emphasis
|
|
role="bold">msg:'Request Missing a Host Header'"</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The msg information appears in the error and/or audit log files
|
|
and is not sent back to the client in response headers.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>multiMatch</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> If enabled
|
|
ModSecurity will perform multiple operator invocations for every target,
|
|
before and after every anti-evasion transformation is performed.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
|
|
SecRule ARGS "attack" <emphasis role="bold">multiMatch</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>noauditlog</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Indicates that a
|
|
successful match of the rule should not be used as criteria whether the
|
|
transaction should be logged to the audit log.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" allow,<emphasis
|
|
role="bold">noauditlog</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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 tranaction will be logged to the audit log. The correct
|
|
way to disable audit logging for the entire transaction is to use
|
|
"<literal moreinfo="none">ctl:auditEngine=Off</literal>"</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>nolog</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Prevents rule
|
|
matches from appearing in both the error and audit logs.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" allow,<emphasis
|
|
role="bold">nolog</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The nolog action also implies noauditlog.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>pass</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Continues processing
|
|
with the next rule in spite of a successful match.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" log,<emphasis
|
|
role="bold">pass</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Transaction will not be interrupted but it will be logged (unless
|
|
logging has been suppressed).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>pause</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Pauses transaction
|
|
processing for the specified number of milliseconds.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403,<emphasis
|
|
role="bold">pause:5000</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>phase</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Places the rule (or
|
|
the rule chain) into one of five available processing phases.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,<emphasis
|
|
role="bold">phase:1</emphasis>,t:removeNulls,t:lowercase
|
|
SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>prepend (Experimental)</title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Prepends text given
|
|
as parameter to the response body. For this action to work content
|
|
injection must be enabled by setting
|
|
<literal>SecContentInjection</literal> to <literal>On</literal>. 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).</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para><emphasis role="bold">Processing Phases:</emphasis> 3 and
|
|
4.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting>SecRule RESPONSE_CONTENT_TYPE ^text/html "phase:3,nolog,pass,<emphasis
|
|
role="bold">prepend:'Header<br>'</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>proxy</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Intercepts
|
|
transaction by forwarding request to another web server using the proxy
|
|
backend.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" log,<emphasis
|
|
role="bold">proxy:http://www.honeypothost.com/</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>redirect</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Intercepts
|
|
transaction by issuing a redirect to the given location.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" \
|
|
log,<emphasis role="bold">redirect:http://www.hostname.com/failed.html</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>If the <literal moreinfo="none">status</literal> 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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>rev</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Specifies rule
|
|
revision.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Metadata</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_METHOD "^PUT$" "id:340002,<emphasis
|
|
role="bold">rev:1</emphasis>,severity:2,msg:'Restricted HTTP function'"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This action is used in combination with the <literal
|
|
moreinfo="none">id</literal> action to allow the same rule ID to be used
|
|
after changes take place but to still provide some indication the rule
|
|
changed.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>sanitiseArg</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Sanitises (replaces
|
|
each byte with an asterisk) a named request argument prior to audit
|
|
logging.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecAction nolog,phase:2,<emphasis
|
|
role="bold">sanitiseArg:password</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>sanitiseMatched</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Sanitises the
|
|
variable (request argument, request header, or response header) that
|
|
caused a rule match.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>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<emphasis>
|
|
password</emphasis> in the name.</para>
|
|
|
|
<programlisting format="linespecific">SecRule ARGS_NAMES password nolog,pass,<emphasis
|
|
role="bold">sanitiseMatched</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Same note as sanitiseArg.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>sanitiseRequestHeader</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Sanitises a named
|
|
request header.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example: This will sanitise the data in the Authorization
|
|
header.</para>
|
|
|
|
<programlisting format="linespecific">SecAction log,phase:1,<emphasis
|
|
role="bold">sanitiseRequestHeader:Authorization</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Same note as sanitiseArg.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>sanitiseResponseHeader</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Sanitises a named
|
|
response header.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example: This will sanitise the Set-Cookie data sent to the
|
|
client.</para>
|
|
|
|
<programlisting format="linespecific">SecAction log,phase:3,<emphasis
|
|
role="bold">sanitiseResponseHeader:Set-Cookie</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Same note as sanitiseArg.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>severity</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Assigns severity to
|
|
the rule it is placed with.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Metadata</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_METHOD "^PUT$" "id:340002,rev:1,<emphasis
|
|
role="bold">severity:2</emphasis>,msg:'Restricted HTTP function'"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>The severity numbers follow the Syslog convention:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>0 = EMERGENCY</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>1 = ALERT</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>2 = CRITICAL</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>3 = ERROR</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>4 = WARNING</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>5 = NOTICE</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>6 = INFO</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>7 = DEBUG</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>setuid</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Special-purpose
|
|
action that initialises the <literal moreinfo="none">USER</literal>
|
|
collection.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecAction <emphasis role="bold">setuid:%{REMOTE_USER}</emphasis>,nolog</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>After initialisation takes place the variable <literal
|
|
moreinfo="none">USERID</literal> will be available for use in the
|
|
subsequent rules.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>setsid</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis>
|
|
Special-purposeaction that initialises the <literal
|
|
moreinfo="none">SESSION</literal> collection.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:
|
|
</emphasis>Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific"># Initialise session variables using the session cookie value
|
|
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
|
|
SecAction <emphasis role="bold">setsid:%{REQUEST_COOKIES.PHPSESSID}</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>On first invocation of this action the collection will be empty
|
|
(not taking the pre-defined variables into account - see <literal
|
|
moreinfo="none">initcol</literal> 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<literal moreinfo="none"> SESSIONID</literal> 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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>setenv</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Creates, removes, or
|
|
updates an environment variable.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Examples:</para>
|
|
|
|
<para>To create a new variable (if you omit the value <literal
|
|
moreinfo="none">1</literal> will be used):</para>
|
|
|
|
<programlisting format="linespecific">setenv:name=value</programlisting>
|
|
|
|
<para>To remove a variable:</para>
|
|
|
|
<programlisting format="linespecific">setenv:!name</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>This action can be used to establish communication with other
|
|
Apache modules.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>setvar</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Creates, removes, or
|
|
updates a variable in the specified collection.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Examples:</para>
|
|
|
|
<para>To create a new variable:</para>
|
|
|
|
<programlisting format="linespecific">setvar:tx.score=10</programlisting>
|
|
|
|
<para>To remove a variable prefix the name with exclamation mark:</para>
|
|
|
|
<programlisting format="linespecific">setvar:!tx.score</programlisting>
|
|
|
|
<para>To increase or decrease variable value use <literal
|
|
moreinfo="none">+</literal> and <literal moreinfo="none">-</literal>
|
|
characters in front of a numerical value:</para>
|
|
|
|
<programlisting format="linespecific">setvar:tx.score=+5</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>skip</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Skips one or more
|
|
rules (or chains) on successful match.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<para><programlisting format="linespecific">SecRule REQUEST_URI "^/$" "chain,<emphasis
|
|
role="bold">skip:2</emphasis>"
|
|
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'"</programlisting></para>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>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 paramater denoting the number of rules (or chains) to
|
|
skip.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>status</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Specifies the
|
|
response status code to use with actions<literal moreinfo="none">
|
|
deny</literal> and<literal moreinfo="none"> redirect</literal>.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis> Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,<emphasis
|
|
role="bold">status:403</emphasis>,phase:1</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Staus actions defined in Apache scope locations (such as
|
|
Directory, Location, etc...) may be superceded 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.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>t</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> 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.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
|
|
SecRule REQUEST_COOKIES:SESSIONID "47414e81cbbef3cf8366e84eeacba091" \
|
|
log,deny,status:403,<emphasis role="bold">t:md5</emphasis></programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Any transformation functions that you specify in a SecRule will be
|
|
in addtion to previous ones specified in SecDefaultAction. Use of
|
|
"t:none" will remove all transformation functions for the specified
|
|
rule.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>xmlns</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This action should
|
|
be used together with an XPath expression to register a
|
|
namespace.</para>
|
|
|
|
<para><emphasis role="bold">Action Group:</emphasis>
|
|
Non-Disruptive</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:Content-Type "text/xml" \
|
|
phase:1,pass,ctl:requestBodyProcessor=XML,ctl:requestBodyAccess=On,<emphasis
|
|
role="bold">xmlns:xsd="http://www.w3.org/2001/XMLSchema"</emphasis>
|
|
SecRule XML:/soap:Envelope/soap:Body/q1:getInput/id() "123" phase:2,deny</programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="08-operators">
|
|
<title>Operators</title>
|
|
|
|
<para>A number of operators can be used in rules, as documented below. The
|
|
operator syntax used the "@" symbol followed by the specific operator
|
|
name.</para>
|
|
|
|
<section>
|
|
<title><literal>beginsWith</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
string comparison and returns true if the parameter value is found at
|
|
the beginning of the input. Macro expansion is performed so you may use
|
|
variable names such as %{TX.1}, etc.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_LINE "!<emphasis
|
|
role="bold">@beginsWith GET</emphasis>" t:none,deny,status:403
|
|
SecRule REQUEST_ADDR "^(.*)\.\d+$" deny,status:403,capture,chain
|
|
SecRule ARGS:gw "!<emphasis role="bold">@beginsWith %{TX.1}</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>contains</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
string comparison and returns true if the parameter value is found
|
|
anywhere in the input. Macro expansion is performed so you may use
|
|
variable names such as %{TX.1}, etc.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_LINE "!<emphasis
|
|
role="bold">@contains .php</emphasis>" t:none,deny,status:403
|
|
SecRule REQUEST_ADDR "^(.*)$" deny,status:403,capture,chain
|
|
SecRule ARGS:ip "!<emphasis role="bold">@contains %{TX.1}</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>endsWith</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
string comparison and returns true if the parameter value is found at
|
|
the end of the input. Macro expansion is performed so you may use
|
|
variable names such as %{TX.1}, etc.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_LINE "!<emphasis
|
|
role="bold">@endsWith HTTP/1.1</emphasis>" t:none,deny,status:403
|
|
SecRule ARGS:route "!<emphasis role="bold">@endsWith %{REQUEST_ADDR}</emphasis>" t:none,deny,status:403</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>eq</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
numerical comparison and stands for "equal to."</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS_NAMES "<emphasis
|
|
role="bold">@eq</emphasis> 15"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>ge</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
numerical comparison and stands for "greater than or equal to."</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS_NAMES "<emphasis
|
|
role="bold">@ge</emphasis> 15"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>geoLookup</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator looks
|
|
up various data fields from an IP address or hostname. The results will
|
|
be captured in the <literal moreinfo="none">GEO</literal>
|
|
collection.</para>
|
|
|
|
<para>You must provide a database via <literal
|
|
moreinfo="none">SecGeoLookupsDb</literal> before this operator can be
|
|
used.</para>
|
|
|
|
<para>See the <literal moreinfo="none">GEO</literal> variable for an
|
|
example and more information on various fields available.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>gt</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
numerical comparison and stands for "greater than."</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS_NAMES "<emphasis
|
|
role="bold">@gt</emphasis> 15"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>inspectFile</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Executes the
|
|
external script/binary given as parameter to the operator against every
|
|
file extracted from the request.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule FILES_TMPNAMES "<emphasis
|
|
role="bold">@inspectFile</emphasis> /opt/apache/bin/inspect_script.pl"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>le</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
numerical comparison and stands for "less than or equal to."</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS_NAMES "<emphasis
|
|
role="bold">@le</emphasis> 15"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>lt</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
numerical comparison and stands for "less than."</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS_NAMES "<emphasis
|
|
role="bold">@lt</emphasis> 15"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>pm</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Phrase Match
|
|
operator. This operator uses a set based matching engine (Aho-Corasick)
|
|
for faster matches of keyword lists. It will match any one of its
|
|
arguments anywhere in the target value.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "<emphasis
|
|
role="bold">@pm</emphasis> WebZIP WebCopier Webster WebStripper SiteSnagger ProWebWalker CheeseBot" "deny,status:403</programlisting>
|
|
|
|
<para>The above would deny access with 403 if any of the words matched
|
|
within the User-Agent HTTP header value.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>pmFromFile</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Phrase Match
|
|
operator. This operator uses a set based matching engine (Aho-Corasick)
|
|
for faster matches of keyword lists. This operator is the same as
|
|
<literal>@pm</literal> except that it takes a list of files as
|
|
arguments. It will match any one of the phrases listed in the file(s)
|
|
anywhere in the target value.</para>
|
|
|
|
<para>Notes:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>The contents of the files should be one phrase per line. End
|
|
of line markers will be stripped from the phrases, however,
|
|
whitespace will not be trimmed from phrases in the file. Empty lines
|
|
and comment lines (beginning with a '#') are ignored.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>To allow easier inclusion of phrase files with rulesets,
|
|
relative paths may be used to the phrase files. In this case, the
|
|
path of the file containing the rule is prepended to the phrase file
|
|
path.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "<emphasis
|
|
role="bold">@pm</emphasis> /path/to/blacklist1 blacklist2" "deny,status:403</programlisting>
|
|
|
|
<para>The above would deny access with 403 if any of the patterns in the
|
|
two files matched within the User-Agent HTTP header value. The
|
|
<literal>blacklist2</literal> file would need to be placed in the same
|
|
path as the file containing the rule.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>rbl</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Look up the
|
|
parameter in the RBL given as parameter. Parameter can be an IPv4
|
|
address, or a hostname.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REMOTE_ADDR "<emphasis
|
|
role="bold">@rbl</emphasis> sc.surbl.org"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>rx</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Regular expression
|
|
operator. This is the default operator, so if the "@" operator is not
|
|
defined, it is assumed to be rx.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "<emphasis
|
|
role="bold">@rx</emphasis> nikto"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>Regular expressions are handled by the PCRE library (<ulink
|
|
url="http://www.pcre.org">http://www.pcre.org</ulink>). ModSecurity
|
|
compiles its regular expressions with the following settings:</para>
|
|
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>The entire input is treated as a single line, even when there
|
|
are newline characters present.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>All matches are case-sensitive. If you do not care about case
|
|
sensitivity you either need to implement the <literal
|
|
moreinfo="none">lowercase</literal> transformational function, or
|
|
use the per-pattern<literal
|
|
moreinfo="none">(?i)</literal>modificator, as allowed by
|
|
PCRE.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The <literal moreinfo="none">PCRE_DOTALL</literal> and
|
|
<literal moreinfo="none">PCRE_DOLLAR_ENDONLY</literal> flags are set
|
|
during compilation, meaning a single dot will match any character,
|
|
including the newlines and a <literal moreinfo="none">$</literal>
|
|
end anchor will not match a trailing newline charater.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>streq</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
string comparison and returns true if the parameter value matches the
|
|
input exactly. Macro expansion is performed so you may use variable
|
|
names such as %{TX.1}, etc.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule ARGS:foo "!<emphasis
|
|
role="bold">@streq bar</emphasis>" t:none,deny,status:403
|
|
SecRule REQUEST_ADDR "^(.*)$" deny,status:403,capture,chain
|
|
SecRule REQUEST_HEADERS:Ip-Address "!<emphasis role="bold">@streq %{TX.1}</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>validateByteRange</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Validates the byte
|
|
range used in the variable falls into the specified range.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule ARG:text "<emphasis
|
|
role="bold">@validateByteRange</emphasis> 10, 13, 32-126"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>You can force requests to consist only of bytes from a certain
|
|
byte range. This can be useful to avoid stack overflow attacks (since
|
|
they usually contain "random" binary content). Default range values are
|
|
0 and 255, i.e. all byte values are allowed. This directive does not
|
|
check byte range in a POST payload when multipart/form-data encoding
|
|
(file upload) is used. Doing so would prevent binary files from being
|
|
uploaded. However, after the parameters are extracted from such request
|
|
they are checked for a valid range.</para>
|
|
|
|
<para>validateByteRange is similar to the ModSecurity 1.X
|
|
SecFilterForceByteRange Directive however since it works in a rule
|
|
context, it has the following differences:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>You can specify a different range for different
|
|
variables.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>It has an "event" context (id, msg....)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>It is executed in the flow of rules rather than being a built
|
|
in pre-check.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>validateDTD</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator
|
|
requires the request body to be processed as XML.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,status:403,phase:2
|
|
SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \
|
|
phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML
|
|
SecRule REQBODY_PROCESSOR "!^XML$" nolog,pass,skip:1
|
|
SecRule XML "<emphasis role="bold">@validateDTD /path/to/apache2/conf/xml.dtd</emphasis>"</programlisting>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>validateSchema</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator
|
|
requires the request body to be processed as XML.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,status:403,phase:2
|
|
SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \
|
|
phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML
|
|
SecRule REQBODY_PROCESSOR "!^XML$" nolog,pass,skip:1
|
|
SecRule XML "<emphasis role="bold">@validateSchema /path/to/apache2/conf/xml.xsd</emphasis>"</programlisting>
|
|
|
|
<para>This operator requires request body to be processed as XML.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>validateUrlEncoding</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Verifies the
|
|
encodings used in the variable (if any) are valid.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule ARGS "<emphasis
|
|
role="bold">@validateUrlEncoding</emphasis>"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>URL encoding is an HTTP standard for encoding byte values within a
|
|
URL. The byte is escaped with a % followed by two hexadecimal values
|
|
(0-F). This directive does not check encoding in a POST payload when the
|
|
multipart/form-data encoding (file upload) is used. It is not necessary
|
|
to do so because URL encoding is not used for this encoding.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>validateUtf8Encoding</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> Verifies the
|
|
variable is a valid UTF-8 encoded string.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule ARGS "<emphasis
|
|
role="bold">@validateUtf8Encoding</emphasis>"</programlisting>
|
|
|
|
<para><emphasis role="bold">Note</emphasis></para>
|
|
|
|
<para>UTF-8 encoding is valid on most web servers. Integer values
|
|
between 0-65535 are encoded in a UTF-8 byte sequence that is escaped by
|
|
percents. The short form is two bytes in length.</para>
|
|
|
|
<para>check for three types of errors:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Not enough bytes. UTF-8 supports two, three, four, five, and
|
|
six byte encodings. ModSecurity will locate cases when a byte or
|
|
more is missing.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Invalid encoding. The two most significant bits in most
|
|
characters are supposed to be fixed to 0x80. Attackers can use this
|
|
to subvert Unicode decoders.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Overlong characters. ASCII characters are mapped directly into
|
|
the Unicode space and are thus represented with a single byte.
|
|
However, most ASCII characters can also be encoded with two, three,
|
|
four, five, and six characters thus tricking the decoder into
|
|
thinking that the character is something else (and, presumably,
|
|
avoiding the security check).</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title><literal>within</literal></title>
|
|
|
|
<para><emphasis role="bold">Description:</emphasis> This operator is a
|
|
string comparison and returns true if the input value is found anywhere
|
|
within the parameter value. Note that this is similar to
|
|
<literal>@contains</literal>, except that the target and match values
|
|
are reversed. Macro expansion is performed so you may use variable names
|
|
such as %{TX.1}, etc.</para>
|
|
|
|
<para>Example:</para>
|
|
|
|
<programlisting format="linespecific">SecRule REQUEST_METHOD "!<emphasis
|
|
role="bold">@within get,post,head</emphasis>" t:lowercase,deny,status:403
|
|
|
|
SecAction "pass,setvar:'tx.allowed_methods=get,post,head'"
|
|
SecRule REQUEST_METHOD "!<emphasis role="bold">@within %{tx.allowed_methods}</emphasis>" t:lowercase,deny,status:403</programlisting>
|
|
</section>
|
|
</section>
|
|
</article> |