mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-13 21:36:00 +03:00
4163 lines
242 KiB
XML
4163 lines
242 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
|
<article>
|
|
<title><trademark class="registered">ModSecurity</trademark> Reference Manual</title>
|
|
<articleinfo>
|
|
<releaseinfo>Version 2.6.0-trunk (Nov 12, 2009)</releaseinfo>
|
|
<copyright>
|
|
<year>2004-2009</year>
|
|
<holder>Breach Security, Inc. (<ulink url="http://www.breach.com"
|
|
>http://www.breach.com</ulink>)</holder>
|
|
</copyright>
|
|
</articleinfo>
|
|
<section id="introduction">
|
|
<title>Introduction</title>
|
|
<para>ModSecurity is a web application firewall (WAF). With over 70% of attacks now carried out
|
|
over the web application level, organisations need all the help they can get in making their
|
|
systems secure. WAFs are deployed to establish an increased external security layer to detect
|
|
and/or prevent attacks before they reach web applications. ModSecurity 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 logging 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, ensuring only the relevant data is recorded. As some of the request
|
|
and/or response may contain sensitive data in certain fields, ModSecurity can be configured
|
|
to mask these fields before they are written to the audit log.</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. A 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 a positive security model is deployed, only requests
|
|
that are known to be valid are accepted, with everything else rejected. This model
|
|
requires knownledge of the web applications you are protecting. Therefore a positive
|
|
security model works best with applications that are heavily used but rarely updated so
|
|
that maintenance of the model is minimized.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Known weaknesses and vulnerabilities. Its rule language makes ModSecurity an ideal
|
|
external patching tool. External patching (sometimes referred to as Virtual Patching) is
|
|
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 applied to the application.</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 is designed to be easy to use, yet flexible:
|
|
common operations are simple while complex operations are possible. Certified ModSecurity
|
|
Rules, included with ModSecurity, contain a comprehensive set of rules that implement
|
|
general-purpose hardening, protocol validation and detection of 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 if required.</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>
|
|
</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>
|
|
<title>Portability</title>
|
|
<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.</para>
|
|
</section>
|
|
<section id="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, ModSecurity Pro, and ModSecurity Core Rules are trademarks
|
|
or registered trademarks of Breach Security, Inc.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<title><trademark>ModSecurity Core Rules</trademark></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.x. Unlike intrusion detection and
|
|
prevention systems, which rely on signatures 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 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="installation">
|
|
<title>Installation</title>
|
|
<para>ModSecurity installation requirements:</para>
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>ModSecurity 2.x works only with Apache 2.0.x or higher. Version 2.2.x is highly
|
|
recommended.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Make sure you have <literal moreinfo="none">mod_unique_id</literal> installed.</para>
|
|
<para>mod_unique_id is packaged with Apache httpd.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>libapr and libapr-util</para>
|
|
<para><ulink type="" url="http://apr.apache.org/">http://apr.apache.org/</ulink></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>libpcre</para>
|
|
<para><ulink type="" url="http://www.pcre.org/">http://www.pcre.org/</ulink></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>libxml2</para>
|
|
<para><ulink type="" url="http://xmlsoft.org/downloads.html"
|
|
>http://xmlsoft.org/downloads.html</ulink></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>liblua v5.1.x</para>
|
|
<para>This library is optional and only needed if you will be using the new Lua
|
|
engine.</para>
|
|
<para><ulink type="" url="http://www.lua.org/download.html"
|
|
>http://www.lua.org/download.html</ulink></para>
|
|
<para>Note that ModSecurity requires the dynamic libraries. These are not built by default
|
|
in the source distribution, so the binary distribution is recommended.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>libcurl v7.15.1 or higher</para>
|
|
<para>If you will be using the ModSecurity Log Collector (mlogc) to send audit logs to a
|
|
central repository, then you will also need the curl library.</para>
|
|
<para><ulink type="" url="http://curl.haxx.se/libcurl/"
|
|
>http://curl.haxx.se/libcurl/</ulink></para>
|
|
<note>
|
|
<para>Many have had issues with libcurl linked with the GnuTLS library for SSL/TLS
|
|
support. It is recommended that the openssl library be used for SSL/TLS support in
|
|
libcurl.</para>
|
|
</note>
|
|
</listitem>
|
|
</orderedlist>
|
|
<para>ModSecurity installation consists of the following steps:</para>
|
|
<orderedlist continuation="restarts" inheritnum="ignore">
|
|
<listitem>
|
|
<para>Stop Apache httpd</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Unpack the ModSecurity archive</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Building differs for UNIX (or UNIX-like) operating systems and Windows.</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>UNIX</para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>Run the configure script to generate a Makefile. Typically no options are
|
|
needed.</para>
|
|
<para><literal>./configure</literal></para>
|
|
<para>Options are available for more customization (use <literal>./configure
|
|
--help</literal> for a full list), but typically you will only need to specify
|
|
the location of the <literal>apxs</literal> command installed by Apache httpd with
|
|
the <literal>--with-apxs</literal> option.</para>
|
|
<para><literal>./configure
|
|
--with-apxs=/path/to/httpd-2.x.y/bin/apxs</literal></para>
|
|
<note>
|
|
<para>There are certain configure options that are meant for debugging an other
|
|
development use. If enabled, these options can substantially impact performance.
|
|
These options include all <literal>--debug-*</literal> options as well as the
|
|
<literal>--enable-performance-measurements</literal> options.</para>
|
|
</note>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Compile with: <literal>make</literal></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Optionally test with: <literal>make test</literal></para>
|
|
<note>
|
|
<para>This is step is still a bit experimental. If you have problems, please send
|
|
the full output and error from the build to the support list. Most common issues
|
|
are related to not finding the required headers and/or libraries.</para>
|
|
</note>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Optionally build the ModSecurity Log Collector with: <literal>make
|
|
mlogc</literal></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Optionally install <literal>mlogc</literal>: Review the <literal
|
|
>INSTALL</literal> file included in the apache2/mlogc-src directory in the
|
|
distribution.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Install the ModSecurity module with: <literal>make install</literal></para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Windows (MS VC++ 8)</para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>Edit <literal>Makefile.win</literal> to configure the Apache base and library
|
|
paths.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Compile with: <literal>nmake -f Makefile.win</literal></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Install the ModSecurity module with: <literal>nmake -f Makefile.win
|
|
install</literal></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Copy the <literal>libxml2.dll</literal> and <literal>lua5.1.dll</literal> to
|
|
the Apache <literal>bin</literal> directory. Alternatively you can follow the step
|
|
below for using LoadFile to load these libraries.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Edit the main Apache httpd config file (usually <literal>httpd.conf</literal>)</para>
|
|
<para>On UNIX (and Windows if you did not copy the DLLs as stated above) you must load
|
|
libxml2 and lua5.1 before ModSecurity with something like this:</para>
|
|
<para>
|
|
<programlisting>LoadFile /usr/lib/libxml2.so
|
|
LoadFile /usr/lib/liblua5.1.so</programlisting>
|
|
</para>
|
|
<para>Load the ModSecurity module
|
|
with:<programlisting>LoadModule security2_module modules/mod_security2.so</programlisting></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Configure ModSecurity</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Start Apache httpd</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>You should 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 (via the <literal>--with-pcre</literal> ModSecurity configure option).</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>
|
|
<para>Non-gcc compilers may have problems running out-of-the-box as the current build system
|
|
was designed around the gcc compiler and some compiler/linker flags may differ. To use a
|
|
non-gcc compiler you may need some manual Makefile tweaks if issues cannot be solved by
|
|
exporting custom CFLAGS and CPPFLAGS environment variables.</para>
|
|
<para>If you are upgrading from ModSecurity 1.x, please refer to the migration matrix at
|
|
<ulink type=""
|
|
url="http://www.modsecurity.org/documentation/ModSecurity-Migration-Matrix.pdf"
|
|
>http://www.modsecurity.org/documentation/ModSecurity-Migration-Matrix.pdf</ulink></para>
|
|
</note>
|
|
</section>
|
|
<section id="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. The
|
|
first version to use a given directive is given in the Version 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 evaluated 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>
|
|
<note>
|
|
<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>
|
|
</note>
|
|
<section>
|
|
<title><literal>SecAction</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAction action1,action2,action3</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAction
|
|
nolog,phase:1,initcol:RESOURCE=%{REQUEST_FILENAME}</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<para>SecAction is best used when you unconditionally 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 certain actions such as
|
|
<literal>initcol</literal> to initialize collections.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecArgumentSeparator</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecArgumentSeparator character</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecArgumentSeparator ;</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Main</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<para>This directive is needed if a backend web application is using a non-standard argument
|
|
separator. If this directive is not set properly for each web application, then ModSecurity
|
|
will not be able to parse the arguments appropriately and the effectiveness of the rule
|
|
matching will be significantly decreased.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecAuditEngine</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the audit logging engine.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditEngine On|Off|RelevantOnly</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditEngine On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Can be set/changed with the "<literal
|
|
>ctl</literal>" action for the current transaction.</para>
|
|
<para>Example: The following example shows the various audit directives used together.</para>
|
|
<programlisting format="linespecific"><emphasis>SecAuditEngine RelevantOnly</emphasis>
|
|
SecAuditLog logs/audit/audit.log
|
|
SecAuditLogParts ABCFHZ
|
|
SecAuditLogType concurrent
|
|
SecAuditLogStorageDir logs/audit
|
|
<emphasis>SecAuditLogRelevantStatus ^(?:5|4\d[^4])</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>Description:</emphasis> Defines the path to the main audit log file.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLog /path/to/auditlog</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLog /usr/local/apache/logs/audit.log</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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 or commercial
|
|
ModSecurity Management Appliance, then you will need to configure and use the ModSecurity
|
|
Log Collector (mlogc) and use the following format for the audit log:</para>
|
|
<para>
|
|
<programlisting format="linespecific">SecAuditLog "|/path/to/mlogc /path/to/mlogc.conf"</programlisting>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecAuditLog2</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLog2 /path/to/auditlog2</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLog2 /usr/local/apache/logs/audit2.log</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.1.2</para>
|
|
<para><emphasis>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>not</emphasis> be used for non-concurrent audit
|
|
logging.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecAuditLogDirMode</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the mode (permissions) of any directories
|
|
created for concurrent audit logs using an octal mode (as used in chmod). See <literal
|
|
moreinfo="none">SecAuditLogFileMode</literal> for controlling the mode of audit log
|
|
files.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogDirMode octal_mode|"default"</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogDirMode 02750</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.10</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This feature is not available on operating
|
|
systems not supporting octal file modes. The default mode (0600) only grants read/write
|
|
access to the account writing the file. If access from another account is needed (using
|
|
mpm-itk is a good example), then this directive may be required. However, use this directive
|
|
with caution to avoid exposing potentially sensitive data to unauthorized users. Using the
|
|
value "default" will revert back to the default setting.</para>
|
|
<note>
|
|
<para>The process umask may still limit the mode if it is being more restrictive than the
|
|
mode set using this directive.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecAuditLogFileMode</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the mode (permissions) of any files created
|
|
for concurrent audit logs using an octal mode (as used in chmod). See <literal
|
|
moreinfo="none">SecAuditLogDirMode</literal> for controlling the mode of created audit log
|
|
directories.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogFileMode octal_mode|"default"</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogFileMode 00640</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.10</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This feature is not available on operating
|
|
systems not supporting octal file modes. The default mode (0600) only grants read/write
|
|
access to the account writing the file. If access from another account is needed (using
|
|
mpm-itk is a good example), then this directive may be required. However, use this directive
|
|
with caution to avoid exposing potentially sensitive data to unauthorized users. Using the
|
|
value "default" will revert back to the default setting.</para>
|
|
<note>
|
|
<para>The process umask may still limit the mode if it is being more restrictive than the
|
|
mode set using this directive.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecAuditLogParts</literal></title>
|
|
<para><emphasis>Description:</emphasis> Defines which part of each transaction are going to be
|
|
recorded in audit log. Each part is assigned a single letter. If a letter appears in the
|
|
list then the equivalent part of each transactions will be recorded. See below for the list
|
|
of all parts.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogParts PARTS</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogParts ABCFHZ</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>
|
|
<note>
|
|
<para>Please refer to the ModSecurity Data Formats document for a detailed description of
|
|
every available part.</para>
|
|
</note>
|
|
<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 <literal
|
|
>multipart/form-data</literal> encoding.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal moreinfo="none">K</literal> - This part contains a full list of every rule
|
|
that matched (one per line) in the order they were matched. The rules are fully
|
|
qualified and will thus show inherited actions and default operators. Supported as of
|
|
v2.5.0</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>Description:</emphasis> Configures which response status code is to be
|
|
considered relevant for the purpose of audit logging.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogRelevantStatus REGEX</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogRelevantStatus ^(?:5|4\d[^4])</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Must have the <literal>SecAuditEngine</literal>
|
|
set to <literal>RelevantOnly</literal>. 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>Description:</emphasis> Configures the storage directory where concurrent
|
|
audit log entries are to be stored.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogStorageDir /path/to/storage/dir</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogStorageDir /usr/local/apache/logs/audit</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Configures the type of audit logging mechanism to be
|
|
used.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogType Serial|Concurrent</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecAuditLogType Serial</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Must specify <literal
|
|
>SecAuditLogStorageDir</literal> 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> (Deprecated/Experimental)</title>
|
|
<para><emphasis>Description:</emphasis> Controls caching of transformations. Caching is off by
|
|
default starting with 2.5.6, when it was deprecated and downgraded back to
|
|
experimental.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecCacheTransformations On|Off [options]</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecCacheTransformations On "minlen:64,maxlen:0"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>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 separated):</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">incremental:on|off</literal> - enabling this option will
|
|
cache every transformation instead of just the final transformation. (default:
|
|
off)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal moreinfo="none">maxitems:N</literal> - do not allow more than N
|
|
transformations to be cached. The cache will then be disabled. A zero value is
|
|
interpreted as "unlimited". This option may be useful to limit caching for a form with a
|
|
large number of ARGS. (default: 512)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal moreinfo="none">minlen:N</literal> - do not cache the transformation if the
|
|
value's length is less than N bytes. (default: 32)</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: 1024)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecChrootDir</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the directory path that will be used to
|
|
jail the web server process.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecChrootDir /path/to/chroot/dir</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecChrootDir /chroot</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Main</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This feature is not available on Windows
|
|
builds. 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.builds. Some problems you might encounter with more complex
|
|
setups:</para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>DNS lookups do not work (this is because this feature requires a shared library that
|
|
is loaded on demand, after chroot takes place).</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>You cannot send email from PHP because it uses sendmail and sendmail is outside the
|
|
jail.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>In some cases Apache graceful (reload) no longer works.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
<para>You should be aware that the internal chroot feature might not be 100% reliable. 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. A module,
|
|
working from within Apache, can do things that make it easy to break out of the jail. In
|
|
particular, if you are using any of the modules that fork in the module initialisation phase
|
|
(e.g. <literal>mod_fastcgi</literal>, <literal>mod_fcgid</literal>, <literal
|
|
>mod_cgid</literal>), you are advised to examine each Apache process and observe its
|
|
current working directory, process root, and the list of open files. Consider what your
|
|
options are and make your own decision.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecComponentSignature</literal></title>
|
|
<para><emphasis>Description</emphasis>: Appends component signature to the ModSecurity
|
|
signature.</para>
|
|
<para><emphasis>Syntax</emphasis>: <literal>SecComponentSignature "COMPONENT_NAME/X.Y.Z
|
|
(COMMENT)"</literal></para>
|
|
<para><emphasis>Example usage</emphasis>: <literal>SecComponentSignature "Core
|
|
Rules/1.2.3"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope</emphasis>: Main</para>
|
|
<para><emphasis>Version</emphasis>: 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes</emphasis>: This directive should be used to make the
|
|
presence of significant ModSecurity components known. The entire signature will be recorded
|
|
in transaction audit log. It should be used by ModSecurity module and rule set writers to
|
|
make debugging easier.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecContentInjection</literal></title>
|
|
<para><emphasis>Description:</emphasis> Enables content injection using actions <literal
|
|
>append</literal> and <literal>prepend</literal>.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal>SecContentInjection (On|Off)</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal>SecContentInjection On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope</emphasis>: Any</para>
|
|
<para><emphasis>Version</emphasis>: 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> N/A</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecCookieFormat</literal></title>
|
|
<para><emphasis>Description:</emphasis> Selects the cookie format that will be used in the
|
|
current configuration context.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecCookieFormat 0|1</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecCookieFormat 0</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Path where persistent data (e.g. IP address data,
|
|
session data, etc) is to be stored.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecDataDir /path/to/dir</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecDataDir /usr/local/apache/logs/data</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Main</para>
|
|
<para><emphasis>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>Description:</emphasis> Path to the ModSecurity debug log file.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecDebugLog /path/to/modsec-debug.log</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecDebugLog
|
|
/usr/local/apache/logs/modsec-debug.log</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecDebugLogLevel</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the verboseness of the debug log
|
|
data.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecDebugLogLevel 0|1|2|3|4|5|6|7|8|9</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecDebugLogLevel 4</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Defines the default action to take on a rule
|
|
match.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecDefaultAction action1,action2,action3</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecDefaultAction
|
|
log,auditlog,deny,status:403,phase:2</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Rules following a <literal
|
|
>SecDefaultAction</literal> directive will inherit this setting unless a specific action
|
|
is specified for an individual rule or until another <literal>SecDefaultAction</literal> is
|
|
specified. Take special note that in the logging disruptive actions are not allowed, but
|
|
this can inadvertently be inherited using a disruptive action in <literal
|
|
>SecDefaultAction</literal>.</para>
|
|
<para>The default value is minimal (differing from previous versions):</para>
|
|
<programlisting format="linespecific">SecDefaultAction phase:2,log,auditlog,pass</programlisting>
|
|
<note>
|
|
<para><literal>SecDefaultAction</literal> must specify a disruptive action and a processing
|
|
phase and cannot contain metadata actions.</para>
|
|
</note>
|
|
<warning>
|
|
<para><literal>SecDefaultAction</literal> is <emphasis>not</emphasis> inherited across
|
|
configuration contexts. (For an example of why this may be a problem for you, read the
|
|
following ModSecurity Blog entry <ulink
|
|
url="http://blog.modsecurity.org/2008/07/modsecurity-tri.html"
|
|
>http://blog.modsecurity.org/2008/07/modsecurity-tri.html</ulink>).</para>
|
|
</warning>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecGeoLookupDb</literal></title>
|
|
<para><emphasis>Description:</emphasis> Defines the path to the geographical database
|
|
file.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecGeoLookupDb /path/to/db</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecGeoLookupDb /usr/local/geo/data/GeoLiteCity.dat</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Check out <literal>maxmind.com</literal> for
|
|
free database files.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecGuardianLog</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configuration directive to use the httpd-guardian
|
|
script to monitor for Denial of Service (DoS) attacks.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecGuardianLog |/path/to/httpd-guardian</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecGuardianLog
|
|
|/usr/local/apache/bin/httpd-guardian</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Main</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> By default httpd-guardian will defend against
|
|
clients that send more than 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>SecMarker</literal></title>
|
|
<para><emphasis>Description:</emphasis> Adds a fixed rule marker in the ruleset to be used as
|
|
a target in a <literal>skipAfter</literal> action. A <literal>SecMarker</literal> directive
|
|
essentially creates a rule that does nothing and whose only purpose it to carry the given
|
|
ID.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecMarker ID</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecMarker 9999</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<para>
|
|
<programlisting format="linespecific">SecRule REQUEST_URI "^/$" \
|
|
"chain,t:none,t:urlDecode,t:lowercase,t:normalisePath,<emphasis>skipAfter:99</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:08,severity:4,msg:'Missing a Host Header'"
|
|
SecRule &REQUEST_HEADERS:Accept "@eq 0" \
|
|
"log,deny,log,status:400,id:15,msg:'Request Missing an Accept Header'"
|
|
<emphasis>
|
|
SecMarker 99</emphasis></programlisting>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecPdfProtect</literal></title>
|
|
<para><emphasis>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>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtect On|Off</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtect On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecPdfProtectMethod</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectMethod method</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectMethod TokenRedirection</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<para><emphasis>Default:</emphasis>
|
|
<literal>TokenRedirection</literal></para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecPdfProtectSecret</literal></title>
|
|
<para><emphasis>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 it will break the tokens that
|
|
were sent prior to change. But it's not a big deal even if you change it. It will just force
|
|
download of PDF files with tokens that were issued in the last few seconds.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectSecret secret</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectSecret MyRandomSecretString</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecPdfProtectTimeout</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectTimeout timeout</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectTimeout 10</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<para><emphasis>Default:</emphasis>
|
|
<literal>10</literal></para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecPdfProtectTokenName</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectTokenName name</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecPdfProtectTokenName PDFTOKEN</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<para><emphasis>Default:</emphasis>
|
|
<literal>PDFTOKEN</literal></para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecRequestBodyAccess</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures whether request bodies will be buffered and
|
|
processed by ModSecurity by default.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyAccess On|Off</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyAccess On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This directive is required if you plan to
|
|
inspect request bodies. Inspection can only be carried out in phases 2 and higher, using the
|
|
<literal>REQUEST_BODY</literal> variable/location. If any of these 3 conditions aren't
|
|
satisfied, the inspection will not work.</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>Description:</emphasis> Configures the maximum request body size ModSecurity
|
|
will accept for buffering.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyLimit NUMBER_IN_BYTES</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyLimit 134217728</literal></para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>SecRequestBodyNoFilesLimit</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the maximum request body size ModSecurity
|
|
will accept for buffering, excluding the size of files being transported in the request.
|
|
This directive comes handy to further reduce susceptibility to DoS attacks when someone is
|
|
sending request bodies of very large sizes. Web applications that require file uploads must
|
|
configure <literal>SecRequestBodyLimit</literal> to a high value. Since large files are
|
|
streamed to disk file uploads will not increase memory consumption. However, it's still
|
|
possible for someone to take advantage of a large request body limit and send non-upload
|
|
requests with large body sizes. This directive eliminates that loophole.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyNoFilesLimit NUMBER_IN_BYTES</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyLimit 131072</literal></para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> 1 MB (1048576 bytes) is the default setting.
|
|
This value is very conservative. For most applications you should be able to reduce it down
|
|
to 128 KB or lower. Anything over the limit will be rejected with status code <literal>413
|
|
Request Entity Too Large</literal>. There is a hard limit of 1 GB.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecRequestBodyInMemoryLimit</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the maximum request body size ModSecurity
|
|
will store in memory.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyInMemoryLimit NUMBER_IN_BYTES</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRequestBodyInMemoryLimit 131072</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Configures the maximum response body size that will be
|
|
accepted for buffering.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyLimit NUMBER_IN_BYTES</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyLimit 524228</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>SecResponseBodyLimitAction</literal></title>
|
|
<para><emphasis>Description</emphasis>: Controls what happens once a response body limit,
|
|
configured with <literal>SecResponseBodyLimit</literal>, is encountered. By default
|
|
ModSecurity will reject a response body that is longer than specified. Some web sites,
|
|
however, will produce very long responses making it difficult to come up with a reasonable
|
|
limit. Such sites would have to raise the limit significantly to function properly defying
|
|
the purpose of having the limit in the first place (to control memory consumption). With the
|
|
ability to choose what happens once a limit is reached site administrators can choose to
|
|
inspect only the first part of the response, the part that can fit into the desired limit,
|
|
and let the rest through. Some could argue that allowing parts of responses to go
|
|
uninspected is a weakness. This is true in theory but only applies to cases where the
|
|
attacker controls the output (e.g. can make it arbitrary long). In such cases, however, it
|
|
is not possible to prevent leakage anyway. The attacker could compress, obfuscate, or even
|
|
encrypt data before it is sent back, and therefore bypass any monitoring device.</para>
|
|
<para><emphasis>Syntax</emphasis>: <literal>SecResponseBodyLimitAction
|
|
Reject|ProcessPartial</literal></para>
|
|
<para><emphasis>Example Usage</emphasis>: <literal>SecResponseBodyLimitAction
|
|
ProcessPartial</literal></para>
|
|
<para><emphasis>Processing Phase</emphasis>: N/A</para>
|
|
<para><emphasis>Scope</emphasis>: Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecResponseBodyMimeType</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures which<literal moreinfo="none">
|
|
MIME</literal> types are to be considered for response body buffering.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyMimeType mime/type</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyMimeType text/plain text/html</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Multiple<literal moreinfo="none">
|
|
SecResponseBodyMimeType</literal> directives can be used to add to the list of<literal
|
|
moreinfo="none"> MIME</literal> types. You can also use the special <literal
|
|
>null</literal> value to request ModSecurity to inspect the bodies of the responses that
|
|
do not specify a MIME type.</para>
|
|
<para>The default value is <literal moreinfo="none">text/plain text/html</literal>:</para>
|
|
<programlisting format="linespecific">SecResponseBodyMimeType text/plain text/html</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecResponseBodyMimeTypesClear</literal></title>
|
|
<para><emphasis>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyMimeTypesClear</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyMimeTypesClear</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecResponseBodyAccess</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures whether response bodies are to be buffer
|
|
and analysed or not.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyAccess On|Off</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecResponseBodyAccess On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRule VARIABLES OPERATOR [ACTIONS]</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRule REQUEST_URI "attack" \</literal></para>
|
|
<para><literal> "phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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 ARGS dirty</programlisting>
|
|
<para>Each rule can specify one or more variables:</para>
|
|
<programlisting format="linespecific">SecRule ARGS|REQUEST_HEADERS:User-Agent 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>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>Collections</title>
|
|
<para>A variable can contain one or many pieces of data, depending on the nature of the
|
|
variable and the way it is used. We've seen examples of both approaches in the previous
|
|
section. When a variable can contain more than one value we refer to it as a
|
|
<emphasis>collection</emphasis>.</para>
|
|
<para>Collections are always expanded before a rule is run. For example, the following
|
|
rule:</para>
|
|
<programlisting>SecRule ARGS dirty</programlisting>
|
|
<para>will be expanded to:</para>
|
|
<programlisting>SecRule ARGS:p dirty
|
|
SecRule ARGS:q dirty</programlisting>
|
|
<para>in a requests that has only two parameters, named <literal>p</literal> and <literal
|
|
>q</literal>.</para>
|
|
<para>Collections come in several flavours:</para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>Read-only</term>
|
|
<listitem>
|
|
<para>Created at runtime using transaction data. For example: <literal>ARGS</literal>
|
|
(contains a list of all request parameter values) and <literal
|
|
>REQUEST_HEADERS</literal> (contains a list of all request header values).</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Transient Read/Write</term>
|
|
<listitem>
|
|
<para>The <literal>TX</literal> collection is created (empty) for every transaction.
|
|
Rules can read from it and write to it (using the <literal>setvar</literal> action,
|
|
for example), but the information stored in this collection will not survive the end
|
|
of transaction.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Persistent Read/Write</term>
|
|
<listitem>
|
|
<para>There are several collections that can be written to, but which are persisted to
|
|
the storage backend. These collections are used to track clients across
|
|
transactions. Examples of collections that fall into this type are <literal
|
|
>IP</literal>, <literal>SESSION</literal> and <literal>USER</literal>.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</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> (regular expression)
|
|
operator. You can also explicitly specify the operator you want to use by using <literal
|
|
moreinfo="none">@</literal>, followed by the name of an operator, at the beginning of
|
|
the second <literal>SecRule</literal> parameter:</para>
|
|
<programlisting format="linespecific">SecRule ARGS "@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 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>Operator negation</title>
|
|
<para>Operator results can be negated by using an exclamation mark at the beginning of the
|
|
second parameter. The following rule matches if the word <literal>dirty</literal> does
|
|
<emphasis>not</emphasis> appear in the <literal>User-Agent</literal> request
|
|
header:</para>
|
|
<programlisting>SecRule REQUEST_HEADERS:User-Agent !dirty</programlisting>
|
|
<para>You can use the exclamation mark in combination with any parameter. If you do, the
|
|
exclamation mark needs to go first, followed by the explicit operator reference. The
|
|
following rule has the same effect as the previous example:</para>
|
|
<programlisting>SecRule REQUEST_HEADERS:User-Agent "!@rx dirty"</programlisting>
|
|
<para>If you need to use negation in a rule that is going to be applied to several variables
|
|
then it may not be immediately clear what will happen. Consider the following
|
|
example:</para>
|
|
<programlisting>SecRule ARGS:p|ARGS:q !dirty</programlisting>
|
|
<para>The above rule is identical to:</para>
|
|
<programlisting>SecRule ARGS:p !dirty
|
|
SecRule ARGS:q !dirty</programlisting>
|
|
<warning>
|
|
<para>Negation is applied to operations against individual operations, not agains the
|
|
entire variable list.</para>
|
|
</warning>
|
|
</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>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>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRuleInheritance On|Off</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRuleInheritance Off</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> Before ModSecurity 2.6.x it was not possible
|
|
for resource-specific contexts (e.g.<literal moreinfo="none"> Location</literal>, <literal
|
|
moreinfo="none">Directory</literal>, etc) to override phase 1 rules configured in the main
|
|
server or in the virtual server. Starting with ModSecurity 2.6 this limitation has been
|
|
lifted and the rules and the configuration directives can be freely used across
|
|
configuration contexts.</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">SecRuleEngine On
|
|
SecDefaultAction log,pass,phase:2
|
|
...
|
|
|
|
<VirtualHost *:80>
|
|
ServerName app1.com
|
|
ServerAlias www.app1.com<emphasis>
|
|
SecRuleInheritance Off</emphasis>
|
|
SecDefaultAction log,deny,phase:1,redirect:http://www.site2.com
|
|
...
|
|
</VirtualHost>
|
|
|
|
<VirtualHost *:80>
|
|
ServerName app2.com
|
|
ServerAlias www.app2.com
|
|
<emphasis>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>
|
|
<note>
|
|
<para>Configuration contexts are an Apache concept. Directives <literal
|
|
><Directory></literal>, <literal><Files></literal>, <literal
|
|
><Location></literal> and <literal><VirtualHost></literal> are all used
|
|
to create configuration contexts. For more information please go to the Apache
|
|
documentation section <ulink url="http://httpd.apache.org/docs/2.0/sections.html"
|
|
>Configuration Sections</ulink>.</para>
|
|
</note>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecRuleEngine</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the rules engine.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRuleEngine On|Off|DetectionOnly</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRuleEngine On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This directive can also be controlled 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>Description:</emphasis> Removes matching rules from the parent
|
|
contexts.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRuleUpdateActionById RULEID ACTIONLIST</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRuleRemoveByID 1 2 "9000-9010"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Removes matching rules from the parent
|
|
contexts.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRuleRemoveByMsg REGEX</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRuleRemoveByMsg "FAIL"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>SecRuleScript</literal> (Experimental)</title>
|
|
<para><emphasis>Description:</emphasis> This directive creates a special rule that executes a
|
|
Lua script to decide whether to match or not. The main difference from <literal
|
|
>SecRule</literal> is that there are no targets nor operators. The script can fetch any
|
|
variable from the ModSecurity context and use any (Lua) operator to test them. The second
|
|
optional parameter is the list of actions whose meaning is identical to that of <literal
|
|
>SecRule</literal>.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal>SecRuleScript /path/to/script.lua [ACTIONS]</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRuleScript "/path/to/file.lua" "block"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> None</para>
|
|
<note>
|
|
<para>All Lua scripts are compiled at configuration time and cached in memory. To reload
|
|
scripts you must reload the entire ModSecurity configuration by restarting Apache.</para>
|
|
</note>
|
|
<para>Example script:</para>
|
|
<programlisting>-- Your script must define the <emphasis>main</emphasis> entry
|
|
-- point, as below.
|
|
function main()
|
|
-- Log something at level 1. Normally you shouldn't be
|
|
-- logging anything, especially not at level 1, but this is
|
|
-- just to show you can. Useful for debugging.
|
|
m.log(1, "Hello world!");
|
|
|
|
-- Retrieve one variable.
|
|
local var1 = m.getvar("REMOTE_ADDR");
|
|
|
|
-- Retrieve one variable, applying one transformation function.
|
|
-- The second parameter is a string.
|
|
local var2 = m.getvar("ARGS", "lowercase");
|
|
|
|
-- Retrieve one variable, applying several transformation functions.
|
|
-- The second parameter is now a list. You should note that m.getvar()
|
|
-- requires the use of comma to separate collection names from
|
|
-- variable names. This is because only one variable is returned.
|
|
local var3 = m.getvar("ARGS.p", { "lowercase", "compressWhitespace" } );
|
|
|
|
-- If you want this rule to match return a string
|
|
-- containing the error message. The message <emphasis>must</emphasis> contain the name
|
|
-- of the variable where the problem is located.
|
|
-- return "Variable ARGS:p looks suspicious!"
|
|
|
|
-- Otherwise, simply return nil.
|
|
return nil;
|
|
end</programlisting>
|
|
<para>In this first example we were only retrieving one variable at the time. In this case the
|
|
name of the variable is known to you. In many cases, however, you will want to examine
|
|
variables whose names you won't know in advance, for example script parameters.</para>
|
|
<para>Example showing use of <literal>m.getvars()</literal> to retrieve many variables at
|
|
once:</para>
|
|
<programlisting>function main()
|
|
-- Retrieve script parameters.
|
|
local d = m.getvars("ARGS", { "lowercase", "htmlEntityDecode" } );
|
|
|
|
-- Loop through the paramters.
|
|
for i = 1, #d do
|
|
-- Examine parameter value.
|
|
if (string.find(d[i].value, "<script")) then
|
|
-- Always specify the name of the variable where the
|
|
-- problem is located in the error message.
|
|
return ("Suspected XSS in variable " .. d[i].name .. ".");
|
|
end
|
|
end
|
|
|
|
-- Nothing wrong found.
|
|
return nil;
|
|
end</programlisting>
|
|
<note>
|
|
<para>Go to <ulink url="http://www.lua.org/">http://www.lua.org/</ulink> to find more about
|
|
the Lua programming language. The reference manual too is available online, at <ulink
|
|
url="http://www.lua.org/manual/5.1/">http://www.lua.org/manual/5.1/</ulink>.</para>
|
|
</note>
|
|
<note>
|
|
<para>Lua support is marked as <emphasis>experimental</emphasis> as the way the progamming
|
|
interface may continue to evolve while we are working for the best implementation style.
|
|
Any user input into the programming interface is appreciated.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecRuleUpdateActionById</literal></title>
|
|
<para><emphasis>Description:</emphasis> Updates the action list of the specified rule.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecRuleRemoveById RULEID ACTIONLIST</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecRuleUpdateActionById 12345 deny,status:403</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> Any</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.5.0</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This directive merges the specified action list
|
|
with the rule's action list. There are two limitations. The rule ID cannot be changed, nor
|
|
can the phase. Further note that actions that may be specified multiple times are appended
|
|
to the original.</para>
|
|
<programlisting format="linespecific">SecAction \
|
|
"t:lowercase,phase:2,id:12345,pass,msg:'The Message',log,auditlog"
|
|
SecRuleUpdateActionById 12345 "t:compressWhitespace,deny,status:403,msg:'A new message'</programlisting>
|
|
<para>The example above will cause the rule to be executed as if it was specified as
|
|
follows:</para>
|
|
<programlisting format="linespecific">SecAction \
|
|
"t:lowercase,phase:2,id:12345,log,auditlog,t:compressWhitespace,deny,status:403,msg:'A new message'"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecServerSignature</literal></title>
|
|
<para><emphasis>Description:</emphasis> Instructs ModSecurity to change the data presented in
|
|
the "Server:" response header token.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecServerSignature "WEB SERVER SOFTWARE"</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecServerSignature "Netscape-Enterprise/6.0"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Main</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Configures the directory where temporary files will be
|
|
created.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecTmpDir /path/to/dir</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecTmpDir /tmp</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Configures the directory where intercepted files will
|
|
be stored.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecUploadDir /path/to/dir</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecUploadDir /tmp</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>SecUploadFileMode</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures the mode (permissions) of any uploaded
|
|
files using an octal mode (as used in chmod).</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecUploadFileMode octal_mode|"default"</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecUploadFileMode 0640</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.1.6</para>
|
|
<para><emphasis>Dependencies/Notes:</emphasis> This feature is not available on operating
|
|
systems not supporting octal file modes. The default mode (0600) only grants read/write
|
|
access to the account writing the file. If access from another account is needed (using
|
|
clamd is a good example), then this directive may be required. However, use this directive
|
|
with caution to avoid exposing potentially sensitive data to unauthorized users. Using the
|
|
value "default" will revert back to the default setting.</para>
|
|
<note>
|
|
<para>The process umask may still limit the mode if it is being more restrictive than the
|
|
mode set using this directive.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>SecUploadKeepFiles</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures whether or not the intercepted files will
|
|
be kept after transaction is processed.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecUploadKeepFiles On|Off|RelevantOnly</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecUploadKeepFiles On</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>Description:</emphasis> Creates a partition on the server that belongs to one
|
|
web application.</para>
|
|
<para><emphasis>Syntax:</emphasis>
|
|
<literal moreinfo="none">SecWebAppId "NAME"</literal></para>
|
|
<para><emphasis>Example Usage:</emphasis>
|
|
<literal moreinfo="none">SecWebAppId "WebApp1"</literal></para>
|
|
<para><emphasis>Processing Phase:</emphasis> N/A</para>
|
|
<para><emphasis>Scope:</emphasis> Any</para>
|
|
<para><emphasis>Version:</emphasis> 2.0.0</para>
|
|
<para><emphasis>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>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>
|
|
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 conjunction 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="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 (<literal>REQUEST_HEADERS</literal>)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Request body (<literal>REQUEST_BODY</literal>)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Response headers (<literal>RESPONSE_HEADERS</literal>)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Response body (<literal>RESPONSE_BODY</literal>)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Logging (<literal>LOGGING</literal>)</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
<para>Below is a diagram of the normal Apache request cycle. In the diagram, the 5 ModSecurity
|
|
processing phases are shown.</para>
|
|
<para>
|
|
<graphic contentwidth="5.5in" fileref="apache_request_cycle-modsecurity.jpg" role="" scale=""
|
|
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>phase:2</emphasis>"
|
|
SecRule REQUEST_HEADERS:Host "!^$" "deny,<emphasis>phase:1</emphasis>"</programlisting>
|
|
<note>
|
|
<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> and <literal>skipAfter</literal> actions.</para>
|
|
</note>
|
|
<note>
|
|
<para>The <literal>LOGGING</literal> phase is special. It is executed at the end of each
|
|
transaction no matter what happened in the previous phases. This means it will be processed
|
|
even if the request was intercepted or the <literal>allow</literal> action was used to pass
|
|
the transaction through.</para>
|
|
</note>
|
|
<section>
|
|
<title>Phase Request Headers</title>
|
|
<para>Phase 1 allows you to inspect a transaction of which request headers are available, but
|
|
before a request body (if any) has been read. Place rules into this phase when you want
|
|
something to happen before a body has been read, or if you want to influence how a body will
|
|
be processed (e.g., configure the buffering options or configure request body processors).
|
|
Beware that you won't have complete request information available at this point. If a
|
|
request has a body, there may be further parameters in it. Use phase 2 when you need to
|
|
inspect all request parameters.</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 arguments
|
|
(provided the request body has been read). ModSecurity supports three encoding types for the
|
|
request body phase:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>application/x-www-form-urlencoded</literal> - used to transfer form data
|
|
(used automatically)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal>multipart/form-data</literal> - used for file transfers (used
|
|
automatically)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal>text/xml</literal> - used for passing XML data (must be explicitly
|
|
configured)</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 appropriately 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 disclosure, 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 cannot 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. Note that you must be careful not to inherit a disruptive action
|
|
into a rule in this phase as this is a configuration error in ModSecurity 2.5.0 and later
|
|
versions.</para>
|
|
</section>
|
|
</section>
|
|
<section id="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
|
|
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,t:none,t:lowercase,t:normalisePath"
|
|
SecRule <emphasis>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,t:none,t:lowercase,t:normalisePath"
|
|
SecRule<emphasis> ARGS_NAMES</emphasis> "!^(p|a)$" "t:none,t:lowercase"</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>AUTH_TYPE</emphasis> "basic" log,deny,status:403,phase:1,t:lowercase</programlisting>
|
|
<para><emphasis>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 inspect the <literal
|
|
>REQUEST_HEADERS:Authorization</literal> header.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">ENV</literal></title>
|
|
<para>Collection, requires a single parameter (after colon). The <literal>ENV</literal>
|
|
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>setenv:tag=suspicious</emphasis>
|
|
SecRule <emphasis>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> 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>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> 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>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>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 results of the last <literal
|
|
moreinfo="none">@geoLookup</literal> operator. The collection can be used to match
|
|
geographical fields looked from an IP address or hostname.</para>
|
|
<para>Available since ModSecurity 2.5.0.</para>
|
|
<para>Fields:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis>COUNTRY_CODE:</emphasis> Two character country code. EX: US, GB,
|
|
etc.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>COUNTRY_CODE3:</emphasis> Up to three character country code.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>COUNTRY_NAME:</emphasis> The full country name.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>COUNTRY_CONTINENT:</emphasis> The two character continent that the country
|
|
is located. EX: EU</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>REGION:</emphasis> The two character region. For US, this is state. For
|
|
Canada, providence, etc.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>CITY:</emphasis> The city name if supported by the database.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>POSTAL_CODE:</emphasis> The postal code if supported by the
|
|
database.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>LATITUDE:</emphasis> The latitude if supported by the database.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>LONGITUDE:</emphasis> The longitude if supported by the database.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>DMA_CODE:</emphasis> The metropolitan area code if supported by the
|
|
database. (US only)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>AREA_CODE:</emphasis> The phone system area code. (US only)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecGeoLookupDb /usr/local/geo/data/GeoLiteCity.dat
|
|
...
|
|
SecRule REMOTE_ADDR "<emphasis>@geoLookup</emphasis>" "chain,drop,msg:'Non-GB IP address'"
|
|
SecRule GEO:COUNTRY_CODE "!@streq GB"</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">MATCHED_VAR</literal></title>
|
|
<para>This variable holds the value of the variable that was matched against. It is similar to
|
|
the TX:0, except it can be used for all operators and does not require that the <literal
|
|
moreinfo="none">capture</literal> action be specified.</para>
|
|
<programlisting format="linespecific">SecRule ARGS pattern chain,deny
|
|
...
|
|
SecRule <emphasis>MATCHED_VAR</emphasis> "further scrutiny"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">MATCHED_VAR_NAME</literal></title>
|
|
<para>This variable holds the full name of the variable that was matched against.</para>
|
|
<programlisting format="linespecific">SecRule ARGS pattern setvar:tx.mymatch=%{MATCHED_VAR_NAME}
|
|
...
|
|
SecRule <emphasis>TX:MYMATCH</emphasis> "@eq ARGS:param" deny</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>MODSEC_BUILD</emphasis> "!@ge 02050102" skipAfter:12345
|
|
SecRule ARGS "@pm some key words" id:12345,deny,status:500</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>MULTIPART_CRLF_LF_LINES</literal></title>
|
|
<para>This flag variable will be set to <literal>1</literal> whenever a multi-part request
|
|
uses mixed line terminators. The <literal>multipart/form-data</literal> RFC requires
|
|
<literal>CRLF</literal> sequence to be used to terminate lines. Since some client
|
|
implementations use only <literal>LF</literal> to terminate lines you might want to allow
|
|
them to proceed under certain circumstances (if you want to do this you will need to stop
|
|
using <literal>MULTIPART_STRICT_ERROR</literal> and check each multi-part flag variable
|
|
individually, avoiding <literal>MULTIPART_LF_LINE</literal>). However, mixing <literal
|
|
>CRLF</literal> and <literal>LF</literal> line terminators is dangerous as it can allow
|
|
for evasion. Therefore, in such cases, you will have to add a check for <literal
|
|
>MULTIPART_CRLF_LF_LINES</literal>.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>MULTIPART_STRICT_ERROR</literal></title>
|
|
<para><literal>MULTIPART_STRICT_ERROR</literal> will be set to <literal>1</literal> when any
|
|
of the following variables is also set to <literal>1</literal>: <literal
|
|
>REQBODY_PROCESSOR_ERROR</literal>, <literal>MULTIPART_BOUNDARY_QUOTED</literal>, <literal
|
|
>MULTIPART_BOUNDARY_WHITESPACE</literal>, <literal>MULTIPART_DATA_BEFORE</literal>,
|
|
<literal>MULTIPART_DATA_AFTER</literal>, <literal>MULTIPART_HEADER_FOLDING</literal>,
|
|
<literal>MULTIPART_LF_LINE</literal>, <literal>MULTIPART_SEMICOLON_MISSING</literal>
|
|
<literal>MULTIPART_INVALID_QUOTING</literal>. Each of these variables covers one unusual
|
|
(although sometimes legal) aspect of the request body in <literal>multipart/form-data
|
|
format</literal>. Your policies should <emphasis>always</emphasis> contain a rule to check
|
|
either this variable (easier) or one or more individual variables (if you know exactly what
|
|
you want to accomplish). Depending on the rate of false positives and your default policy
|
|
you should decide whether to block or just warn when the rule is triggered.</para>
|
|
<para>The best way to use this variable is as in the example below:</para>
|
|
<programlisting>SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
|
|
"phase:2,t:none,log,deny,msg:'Multipart request body \
|
|
failed strict validation: \
|
|
PE %{REQBODY_PROCESSOR_ERROR}, \
|
|
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
|
|
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
|
|
DB %{MULTIPART_DATA_BEFORE}, \
|
|
DA %{MULTIPART_DATA_AFTER}, \
|
|
HF %{MULTIPART_HEADER_FOLDING}, \
|
|
LF %{MULTIPART_LF_LINE}, \
|
|
SM %{MULTIPART_SEMICOLON_MISSING}, \
|
|
IQ %{MULTIPART_INVALID_QUOTING}'"</programlisting>
|
|
<para>The <literal>multipart/form-data</literal> parser was upgraded in ModSecurity v2.1.3 to
|
|
actively look for signs of evasion. Many variables (as listed above) were added to expose
|
|
various facts discovered during the parsing process. The <literal
|
|
>MULTIPART_STRICT_ERROR</literal> variable is handy to check on all abnormalities at once.
|
|
The individual variables allow detection to be fine-tuned according to your circumstances in
|
|
order to reduce the number of false positives. Detailed analysis of various evasion
|
|
techniques covered will be released as a separated document at a later date.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>MULTIPART_UNMATCHED_BOUNDARY</literal></title>
|
|
<para>Set to <literal>1</literal> when, during the parsing phase of a <literal
|
|
>multipart/request-body</literal>, ModSecurity encounters what seems like a boundary but
|
|
it is not. Such an event may occur when evasion of ModSecurity is attempted.</para>
|
|
<para>The best way to use this variable is as in the example below:</para>
|
|
<programlisting>SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
|
|
"phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"</programlisting>
|
|
<para>Change the rule from blocking to logging-only if many false positives are
|
|
encountered.</para>
|
|
</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> 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>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>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>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>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>REMOTE_USER</emphasis> "admin"</programlisting>
|
|
<para><emphasis>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> 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> REQBODY_PROCESSOR_ERROR</emphasis> "@eq 1" deny,phase:2</programlisting>
|
|
<note>
|
|
<para>Your policies <emphasis>must</emphasis> have a rule to check <literal
|
|
>REQBODY_PROCESSOR_ERROR</literal> 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> 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).</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>REQUEST_BASENAME</emphasis> "^login\.php$" phase:2,t:none,t:lowercase</programlisting>
|
|
<note>
|
|
<para>Please note that anti-evasion transformations are not applied to this variable by
|
|
default. <literal>REQUEST_BASENAME</literal> will recognise both <literal>/</literal> and
|
|
<literal>\</literal> as path separators.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_BODY</literal></title>
|
|
<para>This variable holds the data in the request body (including <literal
|
|
>POST_PAYLOAD</literal> data). <literal>REQUEST_BODY</literal> should be used if the
|
|
original order of the arguments is important (<literal>ARGS</literal> should be used in all
|
|
other cases). Example:</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>REQUEST_BODY</emphasis> "^username=\w{25,}\&password=\w{25,}\&Submit\=login$"</programlisting>
|
|
<note>
|
|
<para>This variable is only available if the <literal>URLENCODED</literal> request body
|
|
processor parsed a request body. This will occur by default when an <literal
|
|
>application/x-www-form-urlencoded</literal> is detected, or the <literal
|
|
>URLENCODED</literal> request body parser is forced. As of 2.5.7 it is possible to force
|
|
the presence of the <literal>REQUEST_BODY</literal> variable, but only when there is no
|
|
request body processor defined, using the <literal>ctl:forceRequestBodyVariable</literal>
|
|
option in the <literal>REQUEST_HEADERS</literal> phase.</para>
|
|
</note>
|
|
</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> &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> &REQUEST_COOKIES_NAMES:JSESSIONID</emphasis> "@eq 0"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_FILENAME</literal></title>
|
|
<para>This variable holds the relative <literal>REQUEST_URI</literal> minus the <literal
|
|
>QUERY_STRING</literal> part (e.g. /index.php). Example:</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>REQUEST_FILENAME</emphasis> "^/cgi-bin/login\.php$" phase:2,t:none,t:normalisePath</programlisting>
|
|
<note>
|
|
<para>Please note that anti-evasion transformations are not used on <literal
|
|
>REQUEST_FILENAME</literal> by default.</para>
|
|
</note>
|
|
</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 individual headers (by using
|
|
REQUEST_HEADERS<emphasis>:Header-Name</emphasis>). Example: the first example uses
|
|
<literal>REQUEST_HEADERS</literal> as a collection and is applying the <literal
|
|
>validateUrlEncoding</literal> operator against all headers.</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>REQUEST_HEADERS</emphasis> "@validateUrlEncoding"</programlisting>
|
|
<para>Example: the second example is targeting only the <literal>Host</literal> header.</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>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>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>REQUEST_LINE</emphasis> "!(^((?:(?:pos|ge)t|head))|http/(0\.9|1\.0|1\.1)$)" t:none,t:lowercase</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_METHOD</literal></title>
|
|
<para>This variable holds the request method used by the client.</para>
|
|
<para>The following example will trigger if the request method is either <literal
|
|
>CONNECT</literal> or TRACE.</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>REQUEST_METHOD</emphasis> "^((?:connect|trace))$" t:none,t:lowercase</programlisting>
|
|
</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>REQUEST_PROTOCOL</emphasis> "!^http/(0\.9|1\.0|1\.1)$" t:none,t:lowercase</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_URI</literal></title>
|
|
<para>This variable holds the full URL including the <literal>QUERY_STRING</literal> data
|
|
(e.g. /index.php?p=X), however it will never contain a domain name, even if it was provided
|
|
on the request line. It also does not include either the <literal>REQUEST_METHOD</literal>
|
|
or the HTTP version info.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>REQUEST_URI</emphasis> "attack" phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath</programlisting>
|
|
<note>
|
|
<para>Please note that anti-evasion transformations are not used on <literal
|
|
>REQUEST_URI</literal> by default.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">REQUEST_URI_RAW</literal></title>
|
|
<para>Same as <literal>REQUEST_URI</literal> but will contain the domain name if it was
|
|
provided on the request line (e.g. http://www.example.com/index.php?p=X).</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule<emphasis> REQUEST_URI_RAW</emphasis> "http:/" phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath</programlisting>
|
|
<note>
|
|
<para>Please note that anti-evasion transformations are not used on <literal
|
|
>REQUEST_URI_RAW</literal> by default.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal moreinfo="none">RESPONSE_BODY</literal></title>
|
|
<para>This variable holds the data for the response payload.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule<emphasis> 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> RESPONSE_HEADERS</emphasis><emphasis>:X-Cache</emphasis> "MISS"</programlisting>
|
|
<para><emphasis>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>RESPONSE_HEADERS_NAMES</emphasis> "Set-Cookie"</programlisting>
|
|
<para><emphasis>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>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 as generated by Apache.
|
|
Example:</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>RESPONSE_STATUS</emphasis> "^[45]"</programlisting>
|
|
<para><emphasis>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>%{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>SCRIPT_BASENAME</emphasis> "^login\.php$"</programlisting>
|
|
<para><emphasis>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>SCRIPT_FILENAME</emphasis> "^/usr/local/apache/cgi-bin/login\.php$"</programlisting>
|
|
<para><emphasis>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 group id (numerical value) of the group owner of the script.
|
|
Example:</para>
|
|
<programlisting format="linespecific">SecRule <emphasis>SCRIPT_GID</emphasis> "!^46$"</programlisting>
|
|
<para><emphasis>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> SCRIPT_GROUPNAME</emphasis> "!^apache$"</programlisting>
|
|
<para><emphasis>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>SCRIPT_MODE</emphasis> "^(2|3|6|7)$"</programlisting>
|
|
<para><emphasis>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 user id (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> SCRIPT_UID</emphasis> "!^46$"</programlisting>
|
|
<para><emphasis>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>SCRIPT_USERNAME</emphasis> "!^apache$"</programlisting>
|
|
<para><emphasis>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> 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>SERVER_NAME</emphasis> "hostname\.com$"</programlisting>
|
|
<para><emphasis>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>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$" \
|
|
"phase:2,t:none,t:lowercase,t:normalisePath,pass,log,setvar:<emphasis>session.score</emphasis>=+10"
|
|
SecRule<emphasis> SESSION:SCORE</emphasis> "@gt 50" "pass,log,setvar:<emphasis>session.blocked</emphasis>=1"
|
|
SecRule<emphasis> 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>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> 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>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>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> 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>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> 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>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>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>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 request and then it will
|
|
decided whether or not to allow/deny the request through.</para>
|
|
<para>The following is a list of reserved names in the TX collection:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal moreinfo="none">TX:0</literal> - The matching value when using the <literal
|
|
moreinfo="none">@rx</literal> or <literal moreinfo="none">@pm</literal> operator with
|
|
the <literal moreinfo="none">capture</literal> action.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal moreinfo="none">TX:1-TX:9</literal> - The captured subexpression value when
|
|
using the <literal moreinfo="none">@rx</literal> operator with capturing parens and the
|
|
<literal moreinfo="none">capture</literal> action.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<programlisting format="linespecific">SecRule WEBSERVER_ERROR_LOG "does not exist" "phase:5,pass,<emphasis>setvar:tx.score=+5</emphasis>"
|
|
SecRule<emphasis> 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> 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> 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> 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 <literal>validateDTD</literal> and <literal
|
|
>validateSchema</literal>) 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>XML</emphasis>
|
|
SecRule REQBODY_PROCESSOR "<emphasis>!^XML$</emphasis>" skipAfter:12345
|
|
SecRule <emphasis>XML:/employees/employee/name/text()</emphasis> Fred
|
|
SecRule <emphasis>XML:/xq:employees/employee/name/text()</emphasis> Fred \
|
|
id:12345,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="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>Note</emphasis></para>
|
|
<para>There are no default transformation functions as there were in previous versions of
|
|
ModSecurity.</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 ARGS:p "xp_cmdshell" <emphasis>"t:lowercase"</emphasis></programlisting>
|
|
multiple transformation 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 ARGS:p "xp_cmdshell" <emphasis>"t:urlDecode,t:lowercase"</emphasis></programlisting>
|
|
</para>
|
|
<para>One can use the SecDefaultAction command to ensure the translation occurs for every rule
|
|
until the next. Note that transformation actions are additive, so if a rule explicitly list
|
|
actions, the translation actions set by SecDefaultAction are still performed.</para>
|
|
<para>
|
|
<programlisting format="linespecific">SecDefaultAction <emphasis>t:urlDecode,t:lowercase</emphasis></programlisting>
|
|
</para>
|
|
<para>The following transformation functions are supported:</para>
|
|
<section>
|
|
<title><literal>base64Decode</literal></title>
|
|
<para>This function decodes 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>It converts whitespace characters (32, \f, \t, \n, \r, \v, 160) to spaces (ASCII 32) and
|
|
then compresses multiple consecutive space characters into one.</para>
|
|
</section>
|
|
<section>
|
|
<title>cssDecode</title>
|
|
<para>Decodes CSS-encoded characters, as specified at <ulink
|
|
url="http://www.w3.org/TR/REC-CSS2/syndata.html"
|
|
>http://www.w3.org/TR/REC-CSS2/syndata.html</ulink>. This function uses only up to two
|
|
bytes in the decoding process, meaning it is useful to uncover ASCII characters (that
|
|
wouldn't normally be encoded) encoded using CSS encoding, or to counter evasion which is a
|
|
combination of a backslash and non-hexadecimal characters (e.g. <literal
|
|
>ja\vascript</literal> is equivalent to <literal>javascript</literal>).</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>
|
|
<para>This function will convert any entity into a single byte only, possibly resulting in a
|
|
loss of information. It is thus useful to uncover bytes that would otherwise not need to be
|
|
encoded, but it cannot do anything with the characters from the range above 255.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>jsDecode</literal></title>
|
|
<para>Decodes JavaScript escape sequences. If a <literal>\uHHHH</literal> code is in the range
|
|
of <literal>FF01</literal>-<literal>FF5E</literal> (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>length</literal></title>
|
|
<para>This function converts the input to its numeric length (count of bytes).</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>lowercase</literal></title>
|
|
<para>This function converts all characters to lowercase using the current C locale.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>md5</literal></title>
|
|
<para>This function calculates an MD5 hash from input. Note that the computed hash is in a raw
|
|
binary form and may need encoded into text to be usable (for example: <literal
|
|
>t:md5,t:hexEncode</literal>).</para>
|
|
</section>
|
|
<section>
|
|
<title><literal><literal>none</literal></literal></title>
|
|
<para>Not an actual transformation function, but an instruction to ModSecurity to remove all
|
|
transformation functions associated with the current rule.</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 input).</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>normalisePathWin</literal></title>
|
|
<para>Same as <literal>normalisePath</literal>, but will first convert backslash characters to
|
|
forward slashes.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>parityEven7bit</literal></title>
|
|
<para>This function calculates even parity of 7-bit data replacing the 8th bit of each target
|
|
byte with the calculated parity bit.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>parityOdd7bit</literal></title>
|
|
<para>This function calculates odd parity of 7-bit data replacing the 8th bit of each target
|
|
byte with the calculated parity bit.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>parityZero7bit</literal></title>
|
|
<para>This function calculates zero parity of 7-bit data replacing the 8th bit of each target
|
|
byte with a zero parity bit which allows inspection of even/odd parity 7bit data as ASCII7
|
|
data.</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 from input.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>replaceComments</literal></title>
|
|
<para>This function replaces each occurrence of a C-style comments (<literal moreinfo="none"
|
|
>/* ... */</literal>) with a single space (multiple consecutive occurrences 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 transformation
|
|
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 <literal>%xx</literal> like <literal moreinfo="none">urlDecode,
|
|
urlDecodeUni</literal> also decodes <literal moreinfo="none">%uXXXX</literal> encoding. If
|
|
the code is in the range of <literal>FF01</literal>-<literal>FF5E</literal> (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. Note that the computed hash is in a raw
|
|
binary form and may need encoded to be usable (for example: <literal
|
|
>t:sha1,t:hexEncode</literal>).</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="actions">
|
|
<title>Actions</title>
|
|
<para>Each action belongs to one of five groups:</para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>Disruptive actions</term>
|
|
<listitem>
|
|
<para>Cause ModSecurity to do something. In many cases something means block transaction,
|
|
but not in all. For example, the allow action is classified as a disruptive action, but
|
|
it does the opposite of blocking. There can only be one disruptive action per rule (if
|
|
there are multiple disruptive actions present, or inherited, only the last one will take
|
|
effect), or rule chain (in a chain, a disruptive action can only appear in the first
|
|
rule).</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Non-disruptive actions</term>
|
|
<listitem>
|
|
<para>Do something, but that something does not and cannot affect the rule processing
|
|
flow. Setting a variable, or changing its value is an example of a non-disruptive
|
|
action. Non-disruptive action can appear in any rule, including each rule belonging to a
|
|
chain.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Flow actions</term>
|
|
<listitem>
|
|
<para>These actions affect the rule flow (for example <literal>skip</literal> or <literal
|
|
>skipAfter</literal>).</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Meta-data actions</term>
|
|
<listitem>
|
|
<para>Meta-data actions are used to provide more information about rules. Examples include
|
|
<literal>id</literal>, <literal>rev</literal>, <literal>severity</literal> and
|
|
<literal>msg</literal>.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Data actions</term>
|
|
<listitem>
|
|
<para>Not really actions, these are mere containers that hold data used by other actions.
|
|
For example, the <literal>status</literal> action holds the status that will be used for
|
|
blocking (if it takes place).</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
<section>
|
|
<title><literal>allow</literal></title>
|
|
<para><emphasis>Description:</emphasis> Stops rule processing on a successful match and allows
|
|
the transaction to proceed.</para>
|
|
<para><emphasis>Action Group:</emphasis> Disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,<emphasis>allow</emphasis></programlisting>
|
|
<para>Prior to ModSecurity 2.5 the <literal>allow</literal> action would only affect the
|
|
current phase. An <literal>allow</literal> in phase 1 would skip processing the remaining
|
|
rules in phase 1 but the rules from phase 2 would still execute. Starting with v2.5.0
|
|
<literal>allow</literal> was enhanced to allow for fine-grained control of what is done.
|
|
The following rules now apply:</para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>If used one its own, like in the example above, <literal>allow</literal> will affect
|
|
the entire transaction, stopping processing of the current phase but also skipping over
|
|
all other phases apart from the logging phase. (The logging phase is special; it is
|
|
designed to always execute.)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>If used with parameter "phase", <literal>allow</literal> will cause the engine to
|
|
stop processing the current phase. Other phases will continue as normal.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>If used with parameter "request", <literal>allow</literal> will cause the engine to
|
|
stop processing the current phase. The next phase to be processed will be phase <literal
|
|
>RESPONSE_HEADERS</literal>.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
<para>Examples:</para>
|
|
<programlisting># Do not process request but process response.
|
|
SecAction phase:1,allow:request
|
|
|
|
# Do not process transaction (request and response).
|
|
SecAction phase:1,allow
|
|
</programlisting>
|
|
<para>If you want to allow a response through, put a rule in phase <literal
|
|
>RESPONSE_HEADERS</literal> and simply use <literal>allow</literal> on its own:</para>
|
|
<programlisting># Allow response through.
|
|
SecAction phase:3,allow</programlisting>
|
|
</section>
|
|
<section>
|
|
<title>append</title>
|
|
<para><emphasis>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>Action Group:</emphasis> Non-disruptive</para>
|
|
<para><emphasis>Processing Phases:</emphasis> 3 and 4.</para>
|
|
<para>Example:</para>
|
|
<programlisting>SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,pass,<emphasis>append:'<hr>Footer'</emphasis>"</programlisting>
|
|
<note>
|
|
<para>While macro expansion is allowed in the additional content, you are strongly cautioned
|
|
against inserting user defined data fields.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>auditlog</literal></title>
|
|
<para><emphasis>Description:</emphasis> Marks the transaction for logging in the audit
|
|
log.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REMOTE_ADDR "^192\.168\.1\.100$" <emphasis>auditlog</emphasis>,phase:1,allow</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>The auditlog action is now explicit if log is already specified.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>block</literal></title>
|
|
<para><emphasis>Description:</emphasis> Performs the default disruptive action.</para>
|
|
<para><emphasis>Action Group:</emphasis> Disruptive</para>
|
|
<para>It is intended to be used by ruleset writers to signify that the rule was intended to
|
|
block and leaves the "how" up to the administrator. This action is currently a placeholder
|
|
which will just be replaced by the action from the last <literal>SecDefaultAction</literal>
|
|
in the same context. Using the <literal>block</literal> action with the <literal
|
|
>SecRuleUpdateActionById</literal> directive allows a rule to be reverted back to the
|
|
previous <literal>SecDefaultAction</literal> disruptive action.</para>
|
|
<para>In future versions of ModSecurity, more control and functionality will be added to
|
|
define "how" to block.</para>
|
|
<para>Examples:</para>
|
|
<para>In the following example, the second rule will "deny" because of the SecDefaultAction
|
|
disruptive action. The intent being that the administrator could easily change this to
|
|
another disruptive action without editing the actual rules.</para>
|
|
<programlisting format="linespecific">### Administrator defines "how" to block (deny,status:403)...
|
|
SecDefaultAction phase:2,deny,status:403,log,auditlog
|
|
|
|
### Included from a rulest...
|
|
# Intent is to warn for this User Agent
|
|
SecRule REQUEST_HEADERS:User-Agent "perl" "phase:2,<emphasis>pass</emphasis>,msg:'Perl based user agent identified'"
|
|
# Intent is to block for this User Agent, "how" described in SecDefaultAction
|
|
SecRule REQUEST_HEADERS:User-Agent "nikto" "phase:2,<emphasis>block</emphasis>,msg:'Nikto Scanners Identified'"</programlisting>
|
|
<para>In the following example, The rule is reverted back to the <literal>pass</literal>
|
|
action defined in the SecDefaultAction directive by using the <literal
|
|
>SecRuleUpdateActionById</literal> directive in conjuction with the <literal
|
|
>block</literal> action. This allows an administrator to override an action in a 3rd party
|
|
rule without modifying the rule itself.</para>
|
|
<programlisting format="linespecific">### Administrator defines "how" to block (deny,status:403)...
|
|
SecDefaultAction phase:2,pass,log,auditlog
|
|
|
|
### Included from a rulest...
|
|
SecRule REQUEST_HEADERS:User-Agent "nikto" "id:1,phase:2,<emphasis>deny</emphasis>,msg:'Nikto Scanners Identified'"
|
|
|
|
### Added by the administrator
|
|
SecRuleUpdateActionById 1 "<emphasis>block</emphasis>"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>capture</literal></title>
|
|
<para><emphasis>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>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_BODY "^username=(\w{25,})" phase:2,<emphasis>capture</emphasis>,t:none,chain
|
|
SecRule TX:1 "(?:(?:a(dmin|nonymous)))"</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>The 0 data captures the entire REGEX match and 1 captures the data in the first parens,
|
|
etc...</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>chain</literal></title>
|
|
<para><emphasis>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>Action Group:</emphasis> Flow</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific"># Refuse to accept POST requests that do
|
|
# not specify request body length. Do note that
|
|
# this rule should be preceeded by a rule that verifies
|
|
# only valid request methods (e.g. GET, HEAD and POST) are used.
|
|
SecRule REQUEST_METHOD ^POST$<emphasis> chain</emphasis>,t:none
|
|
SecRule REQUEST_HEADERS:Content-Length ^$ t:none</programlisting>
|
|
<note>
|
|
<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), skip and skipAfter
|
|
actions can only be specified on by the chain starter rule.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>ctl</literal></title>
|
|
<para><emphasis>Description:</emphasis> The ctl action allows configuration options to be
|
|
updated for the transaction.</para>
|
|
<para><emphasis>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>ctl:requestBodyProcessor=XML</emphasis></programlisting>
|
|
<para><emphasis>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">ruleRemoveById</literal> (single rule ID, or a single rule
|
|
ID range accepted as parameter)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal moreinfo="none">requestBodyAccess</literal></para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal moreinfo="none">forceRequestBodyVariable</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> and
|
|
<literal moreinfo="none"> forceRequestBodyVariable</literal>, each configuration option
|
|
corresponds to one configuration directive and the usage is identical.</para>
|
|
<para>The <literal>requestBodyProcessor</literal> 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> bodies, respectively. A third
|
|
processor, <literal>XML</literal>, 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>
|
|
<para>The <literal>forceRequestBodyVariable</literal> option allows you to configure the
|
|
<literal>REQUEST_BODY</literal> variable to be set when there is no request body processor
|
|
configured. This allows for inspection of request bodies of unknown types.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>deny</literal></title>
|
|
<para><emphasis>Description:</emphasis> Stops rule processing and intercepts
|
|
transaction.</para>
|
|
<para><emphasis>Action Group:</emphasis> Disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "nikto" "log,<emphasis>deny</emphasis>,msg:'Nikto Scanners Identified'"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>deprecatevar</literal></title>
|
|
<para><emphasis>Description:</emphasis> Decrement counter based on its age.</para>
|
|
<para><emphasis>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>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>Description:</emphasis> Immediately initiate a "connection close" action to
|
|
tear down the TCP connection by sending a FIN packet.</para>
|
|
<para><emphasis>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 phase:1,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>drop</emphasis>,phase:1,msg:'Possible Brute Force Attack'"</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>This action is currently not available on Windows based builds. This action is extremely
|
|
useful when responding to both Brute Force and Denial of Service attacks in that, in both
|
|
cases, you want to minimize both the network bandwidth and the data returned to the client.
|
|
This action causes error message to appear in the log "(9)Bad file descriptor:
|
|
core_output_filter: writing data to the network"</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>exec</literal></title>
|
|
<para><emphasis>Description:</emphasis> Executes an external script/binary supplied as
|
|
parameter. As of v2.5.0, if the parameter supplied to <literal>exec</literal> is a Lua
|
|
script (detected by the <filename>.lua</filename> extension) the script will be processed
|
|
<emphasis>internally</emphasis>. This means you will get direct access to the internal
|
|
request context from the script. Please read the <literal>SecRuleScript</literal>
|
|
documentation for more details on how to write Lua scripts.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific"># The following is going to execute /usr/local/apache/bin/test.sh
|
|
# as a shell script on rule match.
|
|
SecRule REQUEST_URI "^/cgi-bin/script\.pl" \
|
|
"phase:2,t:none,t:lowercase,t:normalisePath,log,<emphasis>exec:/usr/local/apache/bin/test.sh</emphasis>"
|
|
|
|
# The following is going to process /usr/local/apache/conf/exec.lua
|
|
# internally as a Lua script on rule match.
|
|
SecRule ARGS:p attack log,<emphasis>exec:/usr/local/apache/conf/exec.lua</emphasis></programlisting>
|
|
<note>
|
|
<para>The exec action is executed independently from any disruptive actions. External
|
|
scripts will always be called with no parameters. Some transaction information will be
|
|
placed in environment variables. All the usual CGI environment variables will be there.
|
|
You should be aware that forking a threaded process results in all threads being
|
|
replicated in the new process. Forking can therefore incur larger overhead in
|
|
multi-threaded operation. The script you execute must write something (anything) to
|
|
stdout. If it doesn't ModSecurity will assume execution didn't work.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>expirevar</literal></title>
|
|
<para><emphasis>Description:</emphasis> Configures a collection variable to expire after the
|
|
given time in seconds.</para>
|
|
<para><emphasis>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" \
|
|
"phase:2,t:none,t:lowercase,t:normalisePath,log,allow,\
|
|
setvar:session.suspicious=1,<emphasis>expirevar:session.suspicious=3600</emphasis>,phase:1"</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>You should use expirevar actions at the same time that you use setvar actions in order
|
|
to keep the indented expiration time. If they are used on their own (perhaps in a SecAction
|
|
directive) the expire time could get re-set. When variables are removed from collections,
|
|
and there are no other changes, collections are not written to disk at the end of request.
|
|
This is because the variables can always be expired again when the collection is read again
|
|
on a subsequent request.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>id</literal></title>
|
|
<para><emphasis>Description:</emphasis> Assigns a unique ID to the rule or chain.</para>
|
|
<para><emphasis>Action Group:</emphasis> Meta-data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS:Host "@eq 0" \
|
|
"log,<emphasis>id:60008</emphasis>,severity:2,msg:'Request Missing a Host Header'"</programlisting>
|
|
<para><emphasis>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-699,999; unused (available for reservation).</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>700,000-799,999; reserved for Ivan Ristic.</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>Description:</emphasis> Initialises a named persistent collection, either by
|
|
loading data from storage or by creating a new collection in memory.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example: The following example initiates IP address tracking.</para>
|
|
<programlisting format="linespecific">SecAction <emphasis>phase:1,initcol:ip=%{REMOTE_ADDR}</emphasis>,nolog</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Normally you will want to use <emphasis>phase:1</emphasis> along with
|
|
<emphasis>initcol</emphasis> so that the collection is available in all phases.</para>
|
|
<para>Collections are loaded into memory when the initcol action is encountered. The
|
|
collection in storage will be persisted (and the appropriate counters increased)
|
|
<emphasis>only</emphasis> if it was changed during transaction processing.</para>
|
|
<para>See the "Persistant Storage" section for further details.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>log</literal></title>
|
|
<para><emphasis>Description:</emphasis> Indicates that a successful match of the rule needs to
|
|
be logged.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecAction phase:1,initcol:ip=%{REMOTE_ADDR},<emphasis>log</emphasis></programlisting>
|
|
<para><emphasis>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>Description:</emphasis> Allows a data fragment to be logged as part of the
|
|
alert message.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule &ARGS:p "@eq 0" "log,<emphasis>logdata:'%{TX.0}'"</emphasis></programlisting>
|
|
<para><emphasis>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>Description:</emphasis> Assigns a custom message to the rule or chain.</para>
|
|
<para><emphasis>Action Group:</emphasis> Meta-data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule &REQUEST_HEADERS:Host "@eq 0" \
|
|
"log,id:60008<emphasis>,</emphasis>severity:2,<emphasis>msg:'Request Missing a Host Header'"</emphasis></programlisting>
|
|
<para><emphasis>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>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>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>multiMatch</emphasis></programlisting>
|
|
<para><emphasis>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>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>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" allow,<emphasis>noauditlog</emphasis></programlisting>
|
|
<para><emphasis>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 transaction 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>Description:</emphasis> Prevents rule matches from appearing in both the error
|
|
and audit logs.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" allow,<emphasis>nolog</emphasis></programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>The nolog action also implies noauditlog.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>pass</literal></title>
|
|
<para><emphasis>Description:</emphasis> Continues processing with the next rule in spite of a
|
|
successful match.</para>
|
|
<para><emphasis>Action Group:</emphasis> Disruptive</para>
|
|
<para>Example1:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" log,<emphasis>pass</emphasis></programlisting>
|
|
<para>When using <emphasis>pass</emphasis> with SecRule with multiple targets,
|
|
<emphasis>all</emphasis> targets will be processed and <emphasis>all</emphasis>
|
|
non-disruptive actions will trigger for <emphasis>every</emphasis> match found. In the
|
|
second example the TX:test target would be incremented by 1 for each matching
|
|
argument.</para>
|
|
<para>Example2:</para>
|
|
<programlisting format="linespecific">SecRule ARGS "test" log,<emphasis>pass</emphasis>,setvar:TX.test=+1</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>The transaction will not be interrupted but a log will be generated for each matching
|
|
target (unless logging has been suppressed).</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>pause</literal></title>
|
|
<para><emphasis>Description:</emphasis> Pauses transaction processing for the specified number
|
|
of milliseconds.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403,<emphasis>pause:5000</emphasis></programlisting>
|
|
<para><emphasis>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>Description:</emphasis> Places the rule (or the rule chain) into one of five
|
|
available processing phases.</para>
|
|
<para><emphasis>Action Group:</emphasis> Meta-data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,<emphasis>phase:1</emphasis>,t:removeNulls,t:lowercase
|
|
SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403</programlisting>
|
|
<para><emphasis>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</title>
|
|
<para><emphasis>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>Action Group:</emphasis> Non-disruptive</para>
|
|
<para><emphasis>Processing Phases:</emphasis> 3 and 4.</para>
|
|
<para>Example:</para>
|
|
<programlisting>SecRule RESPONSE_CONTENT_TYPE ^text/html "phase:3,nolog,pass,<emphasis>prepend:'Header<br>'</emphasis>"</programlisting>
|
|
<note>
|
|
<para>While macro expansion is allowed in the additional content, you are strongly cautioned
|
|
against inserting user defined data fields.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>proxy</literal></title>
|
|
<para><emphasis>Description:</emphasis> Intercepts transaction by forwarding request to
|
|
another web server using the proxy backend.</para>
|
|
<para><emphasis>Action Group:</emphasis> Disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" log,<emphasis>proxy:http://www.honeypothost.com/</emphasis></programlisting>
|
|
<para><emphasis>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>Description:</emphasis> Intercepts transaction by issuing a redirect to the
|
|
given location.</para>
|
|
<para><emphasis>Action Group:</emphasis> Disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "Test" \
|
|
log,<emphasis>redirect:http://www.hostname.com/failed.html</emphasis></programlisting>
|
|
<para><emphasis>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>Description:</emphasis> Specifies rule revision.</para>
|
|
<para><emphasis>Action Group:</emphasis> Meta-data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_METHOD "^PUT$" "id:340002,<emphasis>rev:1</emphasis>,severity:2,msg:'Restricted HTTP function'"</programlisting>
|
|
<para><emphasis>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>sanitizeArg</literal></title>
|
|
<para><emphasis>Description:</emphasis> Sanitises (replaces each byte with an asterisk) a
|
|
named request argument prior to audit logging.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecAction nolog,phase:2,<emphasis>sanitizeArg:password</emphasis></programlisting>
|
|
<para><emphasis>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>sanitizeMatched</literal></title>
|
|
<para><emphasis>Description:</emphasis> Sanitises the variable (request argument, request
|
|
header, or response header) that caused a rule match.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example: This action can be used to sanitize arbitrary transaction elements when they
|
|
match a condition. For example, the example below will sanitize any argument that contains
|
|
the word<emphasis> password</emphasis> in the name.</para>
|
|
<programlisting format="linespecific">SecRule ARGS_NAMES password nolog,pass,<emphasis>sanitizeMatched</emphasis></programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Same note as sanitizeArg.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>sanitizeRequestHeader</literal></title>
|
|
<para><emphasis>Description:</emphasis> Sanitises a named request header.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example: This will sanitize the data in the Authorization header.</para>
|
|
<programlisting format="linespecific">SecAction log,phase:1,<emphasis>sanitizeRequestHeader:Authorization</emphasis></programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Same note as sanitizeArg.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>sanitizeResponseHeader</literal></title>
|
|
<para><emphasis>Description:</emphasis> Sanitises a named response header.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example: This will sanitize the Set-Cookie data sent to the client.</para>
|
|
<programlisting format="linespecific">SecAction log,phase:3,<emphasis>sanitizeResponseHeader:Set-Cookie</emphasis></programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Same note as sanitizeArg.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>severity</literal></title>
|
|
<para><emphasis>Description:</emphasis> Assigns severity to the rule it is placed with.</para>
|
|
<para><emphasis>Action Group:</emphasis> Meta-data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_METHOD "^PUT$" "id:340002,rev:1,<emphasis>severity:CRITICAL</emphasis>,msg:'Restricted HTTP function'"</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Severity values in ModSecurity follow those of syslog, as below:</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>
|
|
<para>It is possible to specify severity levels using either the numerical values or the text
|
|
values. You should always specify severity levels using the text values. The use of the
|
|
numerical values is deprecated (as of v2.5.0) and may be removed in one of the susequent
|
|
major updates.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>setuid</literal></title>
|
|
<para><emphasis>Description:</emphasis> Special-purpose action that initialises the <literal
|
|
moreinfo="none">USER</literal> collection.</para>
|
|
<para><emphasis>Action Group:</emphasis> Non-disruptive</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecAction <emphasis>setuid:%{REMOTE_USER}</emphasis>,nolog</programlisting>
|
|
<para><emphasis>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>Description:</emphasis> Special-purpose action that initialises the <literal
|
|
moreinfo="none">SESSION</literal> collection.</para>
|
|
<para><emphasis>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>setsid:%{REQUEST_COOKIES.PHPSESSID}</emphasis></programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>On first invocation of this action the collection will be empty (not taking the
|
|
predefined 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>Description:</emphasis> Creates, removes, or updates an environment
|
|
variable.</para>
|
|
<para><emphasis>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>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>Description:</emphasis> Creates, removes, or updates a variable in the
|
|
specified collection.</para>
|
|
<para><emphasis>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>Description:</emphasis> Skips one or more rules (or chains) on successful
|
|
match.</para>
|
|
<para><emphasis>Action Group:</emphasis> Flow</para>
|
|
<para>Example:</para>
|
|
<para>
|
|
<programlisting format="linespecific">SecRule REQUEST_URI "^/$" \
|
|
"phase:2,chain,t:none<emphasis>,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>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 parameter denoting the number of rules (or chains) to skip.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>skipAfter</literal></title>
|
|
<para><emphasis>Description:</emphasis> Skips rules (or chains) on successful match resuming
|
|
rule execution after the specified rule ID or marker (see <literal>SecMarker</literal>) is
|
|
found.</para>
|
|
<para><emphasis>Action Group:</emphasis> Flow</para>
|
|
<para>Example:</para>
|
|
<para>
|
|
<programlisting format="linespecific">SecRule REQUEST_URI "^/$" "chain,t:none,<emphasis>skipAfter:960015</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>Note</emphasis></para>
|
|
<para><literal>SkipAfter</literal> only applies to the current processing phase and not
|
|
necessarily the order in which the rules appear in the configuration file. If you group
|
|
rules by processing phases, then skip should work as expected. This action can not be used
|
|
to skip rules within one chain. Accepts a single parameter denoting the last rule ID to
|
|
skip.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>status</literal></title>
|
|
<para><emphasis>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>Action Group:</emphasis> Data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecDefaultAction log,deny,<emphasis>status:403</emphasis>,phase:1</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Status actions defined in Apache scope locations (such as Directory, Location, etc...)
|
|
may be superseded by phase:1 action settings. The Apache ErrorDocument directive will be
|
|
triggered if present in the configuration. Therefore if you have previously defined a custom
|
|
error page for a given status then it will be executed and its output presented to the
|
|
user.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>t</literal></title>
|
|
<para><emphasis>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>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>t:md5,t:hexEncode</emphasis></programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>Any transformation functions that you specify in a SecRule will be in addition to
|
|
previous ones specified in SecDefaultAction. Use of "t:none" will remove all transformation
|
|
functions for the specified rule.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>tag</literal></title>
|
|
<para><emphasis>Description:</emphasis> Assigns custom text to a rule or chain.</para>
|
|
<para><emphasis>Action Group:</emphasis> Meta-data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_FILENAME "\b(?:n(?:map|et|c)|w(?:guest|sh)|cmd(?:32)?|telnet|rcmd|ftp)\.exe\b" \
|
|
"t:none,t:lowercase,deny,msg:'System Command Access',id:'950002',<emphasis>\
|
|
tag:'WEB_ATTACK/FILE_INJECTION',tag:'OWASP/A2'</emphasis>,severity:'2'"</programlisting>
|
|
<para><emphasis>Note</emphasis></para>
|
|
<para>The tag information appears in the error and/or audit log files. Its intent is to be
|
|
used to automate classification of rules and the alerts generated by rules. Multiple tags
|
|
can be used per rule/chain.</para>
|
|
</section>
|
|
<section>
|
|
<title><literal>xmlns</literal></title>
|
|
<para><emphasis>Description:</emphasis> This action should be used together with an XPath
|
|
expression to register a namespace.</para>
|
|
<para><emphasis>Action Group:</emphasis> Data</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:Content-Type "text/xml" \
|
|
"phase:1,pass,ctl:requestBodyProcessor=XML,ctl:requestBodyAccess=On,<emphasis> \
|
|
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="operators">
|
|
<title>Operators</title>
|
|
<para>A number of operators can be used in rules, as documented below. The operator syntax uses
|
|
the <literal>@</literal> symbol followed by the specific operator name.</para>
|
|
<section>
|
|
<title><literal>beginsWith</literal></title>
|
|
<para><emphasis>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 <literal>%{TX.1}</literal>, etc.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_LINE "!<emphasis>@beginsWith GET</emphasis>" t:none,deny,status:403
|
|
SecRule REQUEST_ADDR "^(.*)\.\d+$" deny,status:403,capture,chain
|
|
SecRule ARGS:gw "!<emphasis>@beginsWith %{TX.1}</emphasis>"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>contains</literal></title>
|
|
<para><emphasis>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>@contains .php</emphasis>" t:none,deny,status:403
|
|
SecRule REQUEST_ADDR "^(.*)$" deny,status:403,capture,chain
|
|
SecRule ARGS:ip "!<emphasis>@contains %{TX.1}</emphasis>"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>endsWith</literal></title>
|
|
<para><emphasis>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>@endsWith HTTP/1.1</emphasis>" t:none,deny,status:403
|
|
SecRule ARGS:route "!<emphasis>@endsWith %{REQUEST_ADDR}</emphasis>" t:none,deny,status:403</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>eq</literal></title>
|
|
<para><emphasis>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>@eq</emphasis> 15"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>ge</literal></title>
|
|
<para><emphasis>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>@ge</emphasis> 15"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>geoLookup</literal></title>
|
|
<para><emphasis>Description:</emphasis> This operator looks up various data fields from an IP
|
|
address or hostname in the target data. The results will be captured in the <literal
|
|
moreinfo="none">GEO</literal> collection.</para>
|
|
<para>You must provide a database via <literal moreinfo="none">SecGeoLookupDb</literal> before
|
|
this operator can be used.</para>
|
|
<note>
|
|
<para>This operator matches and the action is executed on a <emphasis> successful</emphasis>
|
|
lookup. For this reason, you probably want to use the <emphasis>pass,nolog</emphasis>
|
|
actions. This allows for <literal moreinfo="none">setvar</literal> and other
|
|
non-disruptive actions to be executed on a match. If you wish to block on a failed lookup,
|
|
then do something like this (look for an empty GEO collection):</para>
|
|
<programlisting format="linespecific">SecGeoLookupDb /usr/local/geo/data/GeoLiteCity.dat
|
|
...
|
|
SecRule REMOTE_ADDR "@geoLookup" "pass,nolog"
|
|
SecRule &GEO "@eq 0" "deny,status:403,msg:'Failed to lookup IP'"</programlisting>
|
|
</note>
|
|
<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>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>@gt</emphasis> 15"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>inspectFile</literal></title>
|
|
<para><emphasis>Description:</emphasis> Executes the external script/binary given as parameter
|
|
to the operator against every file extracted from the request. As of v2.5.0, if the supplied
|
|
filename is not absolute it is treated as relative to the directory in which the
|
|
configuration file resides. Also as of v2.5.0, if the filename is determined to be a Lua
|
|
script (based on its extension) the script will be processed by the internal engine. As such
|
|
it will have full access to the ModSecurity context.</para>
|
|
<para>Example of using an external binary/script:</para>
|
|
<programlisting format="linespecific"># Execute external script to validate uploaded files.
|
|
SecRule FILES_TMPNAMES "<emphasis>@inspectFile</emphasis> /opt/apache/bin/inspect_script.pl"</programlisting>
|
|
<para>Example of using Lua script:</para>
|
|
<programlisting>SecRule FILES_TMPNANMES "@inspectFile <emphasis>inspect.lua</emphasis>"</programlisting>
|
|
<para>Script <filename>inspect.lua</filename>:</para>
|
|
<programlisting>function main(filename)
|
|
-- Do something to the file to verify it. In this example, we
|
|
-- read up to 10 characters from the beginning of the file.
|
|
local f = io.open(filename, "rb");
|
|
local d = f:read(10);
|
|
f:close();
|
|
|
|
-- Return null if there is no reason to believe there is ansything
|
|
-- wrong with the file (no match). Returning any text will be taken
|
|
-- to mean a match should be trigerred.
|
|
return null;
|
|
end</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>le</literal></title>
|
|
<para><emphasis>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>@le</emphasis> 15"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>lt</literal></title>
|
|
<para><emphasis>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>@lt</emphasis> 15"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>pm</literal></title>
|
|
<para><emphasis>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. The match is case insensitive.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule REQUEST_HEADERS:User-Agent "<emphasis>@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>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>@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>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>@rbl</emphasis> sc.surbl.org"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>rx</literal></title>
|
|
<para><emphasis>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>@rx</emphasis> nikto"</programlisting>
|
|
<para><emphasis>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> transformation
|
|
function, or use the per-pattern<literal moreinfo="none">(?i)</literal>modifier, 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 character.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
<section>
|
|
<title><literal>streq</literal></title>
|
|
<para><emphasis>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>@streq bar</emphasis>" t:none,deny,status:403
|
|
SecRule REQUEST_ADDR "^(.*)$" deny,status:403,capture,chain
|
|
SecRule REQUEST_HEADERS:Ip-Address "!<emphasis>@streq %{TX.1}</emphasis>"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>validateByteRange</literal></title>
|
|
<para><emphasis>Description:</emphasis> Validates the byte range used in the variable falls
|
|
into the specified range.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule ARGS:text "<emphasis>@validateByteRange</emphasis> 10, 13, 32-126"</programlisting>
|
|
<para><emphasis>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 <literal>multipart/form-data</literal> 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>Description:</emphasis> Validates the DOM tree generated by the XML request
|
|
body processor against the supplied DTD.</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,skipAfter:12345
|
|
SecRule XML "<emphasis>@validateDTD /path/to/apache2/conf/xml.dtd</emphasis>" "deny,id:12345"</programlisting>
|
|
<note>
|
|
<para>This operator requires request body to be processed as XML.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>validateSchema</literal></title>
|
|
<para><emphasis>Description:</emphasis> Validates the DOM tree generated by the XML request
|
|
body processor against the supplied XML Schema.</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,skipAfter:12345
|
|
SecRule XML "<emphasis>@validateSchema /path/to/apache2/conf/xml.xsd</emphasis>" "deny,id:12345"</programlisting>
|
|
<note>
|
|
<para>This operator requires request body to be processed as XML.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title><literal>validateUrlEncoding</literal></title>
|
|
<para><emphasis>Description:</emphasis> Verifies the encodings used in the variable (if any)
|
|
are valid.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule ARGS "<emphasis>@validateUrlEncoding</emphasis>"</programlisting>
|
|
<para><emphasis>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 <literal>multipart/form-data</literal> 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>Description:</emphasis> Verifies the variable is a valid UTF-8 encoded
|
|
string.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule ARGS "<emphasis>@validateUtf8Encoding</emphasis>"</programlisting>
|
|
<para><emphasis>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>verifyCC</literal></title>
|
|
<para><emphasis>Description:</emphasis> This operator verifies a given regular expression as a
|
|
potential credit card number. It first matches with a single generic regular expression then
|
|
runs the resulting match through a Luhn checksum algorithm to further verify it as a
|
|
potential credit card number.</para>
|
|
<para>Example:</para>
|
|
<programlisting format="linespecific">SecRule ARGS "<emphasis>@verifyCC \d{13,16}</emphasis>" \
|
|
"phase:2,sanitizeMatched,log,auditlog,pass,msg:'Potential credit card number'"</programlisting>
|
|
</section>
|
|
<section>
|
|
<title><literal>within</literal></title>
|
|
<para><emphasis>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>@within get,post,head</emphasis>" t:lowercase,deny,status:403
|
|
|
|
SecAction "pass,setvar:'tx.allowed_methods=get,post,head'"
|
|
SecRule REQUEST_METHOD "!<emphasis>@within %{tx.allowed_methods}</emphasis>" t:lowercase,deny,status:403</programlisting>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<title>Macro Expansion</title>
|
|
<para>Macros allow for using place holders in rules that will be expanded out to their values at
|
|
runtime. Currently only variable expansion is supported, however more options may be added in
|
|
future versions of ModSecurity.</para>
|
|
<para>Format:</para>
|
|
<programlisting format="linespecific">%{VARIABLE}
|
|
%{COLLECTION.VARIABLE}</programlisting>
|
|
<para>Macro expansion can be used in actions such as initcol, setsid, setuid, setvar, setenv,
|
|
logdata. Operators that are evaluated at runtime support expansion and are noted above. Such
|
|
operators include @beginsWith, @endsWith, @contains, @within and @streq. You cannot use macro
|
|
expansion for operators that are "compiled" such as @pm, @rx, etc. as these operators have
|
|
their values fixed at configure time for efficiency.</para>
|
|
<para>Some values you may want to expand include: TX, REMOTE_ADDR, USERID, HIGHEST_SEVERITY,
|
|
MATCHED_VAR, MATCHED_VAR_NAME, MULTIPART_STRICT_ERROR, RULE, SESSION, USERID, among
|
|
others.</para>
|
|
</section>
|
|
<section>
|
|
<title>Persistant Storage</title>
|
|
<para>At this time it is only possible to have three collections in which data is stored
|
|
persistantly (i.e. data available to multiple requests). These are: <literal moreinfo="none"
|
|
>IP</literal>, <literal moreinfo="none"> SESSION</literal> and <literal moreinfo="none"
|
|
>USER</literal>.</para>
|
|
<para>Every collection contains several built-in variables that are available and are read-only
|
|
unless otherwise specified:</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">IS_NEW</literal> - set to 1 if the collection is new (not yet
|
|
persisted) otherwise set to 0.</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). This variable may be set
|
|
if you wish to specifiy an explicit expiration time (default is 3600 seconds).</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>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>. To create a collection to hold client address
|
|
variables (<literal moreinfo="none">IP</literal>) use action <literal moreinfo="none"
|
|
>initcol</literal>.</para>
|
|
<note>
|
|
<para>ModSecurity implements atomic updates of persistent variables only for integer variables
|
|
(counters) 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. Counters are
|
|
adjusted by applying a delta generated by re-reading the persisted data just before being
|
|
persisted. This keeps counter data consistent even if the counter was modified and persisted
|
|
by another thread/process during the transaction.</para>
|
|
</note>
|
|
<note>
|
|
<para>ModSecurity uses a Berkley Database (SDBM) for persistant storage. This type of database
|
|
is generally limited to storing a maximum of 1008 bytes per key. This may be a limitation if
|
|
you are attempting to store a considerable amount of data in variables for a single key.
|
|
Some of this limitation is planned to be reduced in a future version of ModSecurity.</para>
|
|
</note>
|
|
</section>
|
|
<section>
|
|
<title>Miscellaneous Topics</title>
|
|
<para/>
|
|
<section>
|
|
<title>Impedance Mismatch</title>
|
|
<para>Web application firewalls have a difficult job trying to make sense of data that passes
|
|
by, without any knowledge of the application and its business logic. The protection they
|
|
provide comes from having an independent layer of security on the outside. Because data
|
|
validation is done twice, security can be increased without having to touch the application.
|
|
In some cases, however, the fact that everything is done twice brings problems. Problems can
|
|
arise in the areas where the communication protocols are not well specified, or where either
|
|
the device or the application do things that are not in the specification. In such cases it
|
|
may be possible to design payload that will be interpreted in one way by one device and in
|
|
another by the other device. This problem is better known as Impedance Mismatch. It can be
|
|
exploited to evade the security devices.</para>
|
|
<para>While we will continue to enhance ModSecurity to deal with various evasion techniques
|
|
the problem can only be minimized, but never solved. With so many different application
|
|
backend chances are some will always do something completely unexpected. The only solution
|
|
is to be aware of the technologies in the backend when writing rules, adapting the rules to
|
|
remove the mismatch. See the next section for some examples.</para>
|
|
<section>
|
|
<title>PHP Peculiarities for ModSecurity Users</title>
|
|
<para>When writing rules to protect PHP applications you need to pay attention to the
|
|
following facts:</para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>When "register_globals" is set to "On" request parameters are automatically
|
|
converted to script variables. In some PHP versions it is even possible to override
|
|
the $GLOBALS array.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Whitespace at the beginning of parameter names is ignored. (This is very dangerous
|
|
if you are writing rules to target specific named variables.)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The remaining whitespace (in parameter names) is converted to underscores. The
|
|
same applies to dots and to a "[" if the variable name does not contain a matching
|
|
closing bracket. (Meaning that if you want to exploit a script through a variable that
|
|
contains an underscore in the name you can send a parameter with a whitespace or a dot
|
|
instead.)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Cookies can be treated as request parameters.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The discussion about variable names applies equally to the cookie names.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The order in which parameters are taken from the request and the environment is
|
|
EGPCS (environment, GET, POST, Cookies, built-in variables). This means that a POST
|
|
parameter will overwrite the parameters transported on the request line (in
|
|
QUERY_STRING).</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>When "magic_quotes_gpc" is set to "On" PHP will use backslash to escape the
|
|
following characters: single quote, double quote, backslash, and the nul byte.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>If "magic_quotes_sybase" is set to "On" only the single quote will be escaped
|
|
using another single quote. In this case the "magic_quotes_gpc" setting becomes
|
|
irrelevant. The "magic_quotes_sybase" setting completely overrides the
|
|
"magic_quotes_gpc" behaviour but "magic_quotes_gpc" still must be set to "On" for the
|
|
Sybase-specific quoting to be work.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>PHP will also automatically create nested arrays for you. For example "p[x][y]=1"
|
|
results in a total of three variables.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
</article>
|