From the Web site: ModSecurity is an open source intrusion detection and prevention engine for web applications (or a web application firewall). Operating as an Apache Web server module or standalone, the purpose of ModSecurity is to increase web application security...
The reference manual and other documentation can be found at the Mod-Security Web site.
apt-get install libapache-mod-security
Get the source code from modsecurity.org/download and follow the instructions given in the reference manual.
First, the module must be loaded by Apache when it starts, so in httpd.conf (or whatever your Apache configuration file is called)
LoadModule security_module /usr/lib/apache/1.3/mod_security.soand perhaps
AddModule mod_security.c
Secondly, the module must be configured, so in http.conf (or whatever...) add
Include mod_security.confor perhaps
<IfModule mod_security.c> Include mod_security.conf </IfModule>with mod_security.conf
# This is a simple illustrative example only; mod_security can do far # more --- see the Reference Manual for more. # -- PART ONE: filter configuration : SecFilterEngine On # filter every request SecFilterScanPOST On # scan body (or POST) payload (disabled by default) SecFilterDefaultAction "deny,log,status:404" # sets default action to return 404 (not found) --- the default default # is 403 (forbidden) # -- PART TWO: rules : SecFilter passwd SecFilter shadow # block requests including "passwd" or "shadow" in the # request string
Logs appear in /var/log/error.log — using a browser to attempt access to http://mctalby.mc.man.ac.uk/~mc/passwd yields:
[Wed Jan 4 13:54:54 2006] [error] [client 130.88.201.157] \ mod_security: Access denied with code 404. Pattern match "passwd" \ at THE_REQUEST. [hostname "mctalby.mc.man.ac.uk"] [uri "/~mc/passwd"]
mod_security can do much more, including:
For each matching rule, mod_security can perform actions:
Use the exec action to execute a script which INSERTs rules into IPTables (or other firewall) which given rules are matched — dangerous. This can be used by those attacking your server to perform a DoS on your machine...
N.B. Apache 1.3 uses POSIX regular expressions; Apache 2.n uses PCRE (Perl-compatible regular expressions).
Many such variables exist, such as REMOTE_HOST and REQUEST_METHOD, which correspond to HTTP MIME headers. There are several additional variables, including:
THE_REQUEST | The full HTTP request line sent by the browser to the server, e.g., GET /index.html HTTP/1.1. This does not include any additional headers sent by the browser. |
REQUEST_URI | The resource requested in the HTTP request line. In the example above, this would be /index.html. |
For the truly paranoid, one can implement a default-deny set of rules, like this:
# ---------------------------------------------------------------------------------------------------- # -- Configuration : # ---------------------------------------------------------------------------------------------------- ## ## see "Configuration" from the "ModSecurity for Apache User Guide" ## for more details ## SecFilterEngine On # ...On = analyse every request SecFilterScanPOST On # ...On = turn on scanning of body payload (or POST payload) --- default is off SecFilterSelective HTTP_Content-Type "!(^$|^application/x-www-form-urlencoded$|^multipart/form-data;)" # ...mod_security supports only two types of body: # # application/x-www-form-urlencoded (used to transfer form data) # multipart/form-data (used for file transfers) # # so allow only these (few web apps use other types)... SecFilterSelective HTTP_Transfer-Encoding "!^$" # ...block chunked-transfer-encoding of requests (not of responses) since mod_security does not # yet support chunked requests (but then nor do any browsers yet either)... SecFilterDefaultAction "deny,log,status:402" # ...default action for a matching rule --- don't accede to the request, log the request (it's # denial, that is) and respond with 404 ("Not found")... # # the default default is 403 ("Forbidden") which sounds bad to me (indicates existence)... SecFilterCheckURLEncoding On # ...On = turn on URL encoding checks (block attacks which use %XY where X, Y are _not_ # in [0-9], [a-f]) SecFilterCheckUnicodeEncoding On # ...On = check encoding of characters is correct for UTF-8 ##SecFilterForceByteRange 32 126 # ...This directive allows only one range to be specified. But one can cheat --- filter on # multiple ranges --- e.g. thusly: # # SecFilterSelective THE_REQUEST "!^[\x0a\x0d\x20-\x7e]+$" # # ...allows characters 10, 13 and 32-126... # # http://www.ascii.cl/htmlcodes.htm : # # 32 -- 126 # NOT 127 # NOT 128 -- 159 # 160 -- 255 # SecFilterSelective THE_REQUEST "!^[\x20-\x7e\xa0-\xff]+$" # ---------------------------------------------------------------------------------------------------- # -- Rules to block directory traversal : # ---------------------------------------------------------------------------------------------------- SecFilter "\.\./" # ...N.B. this matches /path/a../thing but not /patch/../thing because # (quoting Ivan Ristic) Apache is normalizing the path before # mod_security gets to it (you can see it in the debug log if # you increase the verbosity of the log). If you try something # like: # /cgi-bin/modsec-test.pl?p=123/../456 # it will work. Apache only normalizes the data on the # left hand of the question mark character. # ---------------------------------------------------------------------------------------------------- # -- Default deny : # ---------------------------------------------------------------------------------------------------- # -- commands such as # # cat /var/log/apache/access.log | awk '{print $6" "$7" "$8}' | sort -u # # which yields # # "GET / HTTP/1.0" # "GET / HTTP/1.1" # "GET /Password HTTP/1.0" # "GET /Password HTTP/1.1" # "GET /Password/ HTTP/1.0" # "GET /Password/ HTTP/1.1" # "GET /Password/place.jpg HTTP/1.0" # "GET /Password/place.jpg HTTP/1.1" # "GET /icons/apache_pb.png HTTP/1.0" # "GET /icons/apache_pb.png HTTP/1.1" # "GET /icons/debian/openlogo-25.jpg HTTP/1.0" # "GET /icons/debian/openlogo-25.jpg HTTP/1.1" # . # . # # and # # cat /var/log/apache/access.log | awk '{print "SecFilterSelective REQUEST_URI \"^"$7"$\" allow"}' | sort -u # # which writes out ready-made rules and # # cat /var/log/apache/error.log | grep "Warning. Pattern match \".\"" | awk '{print $19}' | sort -u # # are useful in implementing rule-sets. SecFilterSelective REQUEST_URI "^?$", allow SecFilterSelective REQUEST_URI "^?Password$", allow SecFilterSelective REQUEST_URI "^?Password/$", allow SecFilterSelective REQUEST_URI "^?Password/place.jpg$", allow SecFilterSelective REQUEST_URI "^?icons/apache_pb.png$", allow SecFilterSelective REQUEST_URI "^?icons/debian/openlogo-25.jpg$", allow SecFilterSelective REQUEST_URI "^?icons/jhe061.png$", allow SecFilterSelective REQUEST_URI "^?layers.js$", allow SecFilterSelective REQUEST_URI "^?manchester_logo_final.gif$", allow SecFilterSelective REQUEST_URI "^?password/$", allow SecFilterSelective REQUEST_URI "^?selfreg.css$", allow SecFilterSelective REQUEST_URI "^/Password/passform.pl$", allow SecFilterSelective REQUEST_URI ".", deny # ---------------------------------------------------------------------------------------------------- # Time for a nice cup of tea. # ----------------------------------------------------------------------------------------------------
...previous | up (conts) | next... |