logo
Apache Lounge
Webmasters

 

About Forum Index Downloads Search Register Log in RSS X


Keep Server Online

If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.

or

Bitcoin

A donation makes a contribution towards the costs, the time and effort that's going in this site and building.

Thank You! Steffen

Your donations will help to keep this site alive and well, and continuing building binaries. Apache Lounge is not sponsored.
Post new topic   Forum Index -> How-to's & Documentation & Tips View previous topic :: View next topic
Reply to topic   Topic: Hardening rules for mod_security
Author
Steffen
Moderator


Joined: 15 Oct 2005
Posts: 3049
Location: Hilversum, NL, EU

PostPosted: Sun 25 Dec '05 22:08    Post subject: Hardening rules for mod_security Reply with quote

Just to share some mod_security rules with you. When you get false positives for your server, let us know here.

If you have a usefull rule, please post it here.

Code:


<IfModule mod_security.c>
 
# Turn ModSecurity On
SecFilterEngine On
 
#SecFilterScanPOST On
SecFilterCheckURLEncoding On
SecFilterCheckUnicodeEncoding Off
 
# Accept almost all byte values
SecFilterForceByteRange 1 255
 
# Server masking is optional
# SecServerSignature "Steffen :)"
 
#SecUploadDir logs
#SecUploadKeepFiles Off
 
# Only record the interesting stuff
SecAuditEngine RelevantOnly
SecAuditLog logs/sec.log
 
## -- Common attacks --------------------
 
SecFilterDefaultAction "deny,log,msg:'Common attacks',status:403"

#Web Proxy GET Request
SecFilter "^GET (http|https|ftp)\:/"
#Web Proxy HEAD Request
SecFilter "^HEAD (http|https|ftp)\:/"
#Proxy POST Request
SecFilter "^POST (http|https|ftp)\:/"
#Proxy CONNECT Request
SecFilterSelective THE_REQUEST "^CONNECT "
 
# Only accept request encodings we know how to handle.
SecFilterSelective REQUEST_METHOD "!^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Type "!(^application/x-www-form-urlencoded$|^multipart/form-data;)"
 
# Do not accept GET or HEAD requests with bodies
SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Length "!^$"
 
# Restrict which request methods can be used
SecFilterSelective REQUEST_METHOD "!^(GET|HEAD|POST)$"
 
# Restrict protocol versions.
SecFilterSelective SERVER_PROTOCOL "!^HTTP/(0\.9|1\.0|1\.1)$"
 
# Require Content-Length to be provided with every POST request.
SecFilterSelective REQUEST_METHOD "^POST$" chain
SecFilterSelective HTTP_Content-Length "^$"
 
# Don't accept transfer encodings we know we don't know how to handle
SecFilterSelective HTTP_Transfer-Encoding "!^$"
 
## -- PHP attacks --------------------
 
SecFilterSignatureAction "log,deny,msg:'PHP attack'"
 
# Possible code execution attack (targets valid PHP streams constructs)
SecFilterSelective ARGS_NAMES "^php:/"
 
#phpBB attack
SecFilterSelective ARG_highlight "(\x27|%27|\x2527|%2527)"

## -- Awstats-------------------------

SecFilterSignatureAction "log,deny,msg:'Awstats Attack'"
SecFilterSelective ARGS_NAMES "configdir"

## -- SQL Injection Attacks --------------------
 
SecFilterSignatureAction "log,deny,msg:'SQL Injection attack'"
 
# Generic
SecFilterSelective ARGS "delete[[:space:]]+from"
SecFilterSelective ARGS "drop[[:space:]]+database"
SecFilterSelective ARGS "drop[[:space:]]+table"
SecFilterSelective ARGS "drop[[:space:]]+column"
SecFilterSelective ARGS "drop[[:space:]]+procedure"
SecFilterSelective ARGS "create[[::space:]]+table"
SecFilterSelective ARGS "update.+set.+="
SecFilterSelective ARGS "insert[[:space:]]+into.+values"
SecFilterSelective ARGS "select.+from"
SecFilterSelective ARGS "bulk[[:space:]]+insert"
SecFilterSelective ARGS "union.+select"
SecFilterSelective ARGS "or.+1[[:space:]]*=[[:space:]]1"
SecFilterSelective ARGS "alter[[:space:]]+table"
SecFilterSelective ARGS "or 1=1--'"
SecFilterSelective ARGS "'.+--"
 
# MySQL
SecFilterSelective ARGS "into[[:space:]]+outfile"
SecFilterSelective ARGS "load[[:space:]]+data
SecFilterSelective ARGS "/\*.+\*/"
 

## -- Command execution --------------------
 
SecFilterSignatureAction "log,deny,msg:'Command execution attack'"
 
SecFilterSelective ARGS_VALUES "^(uname|id|ls|rm|kill)"
SecFilterSelective ARGS_VALUES "^(ls|id|pwd|wget)"
SecFilterSelective ARGS_VALUES ";[[:space:]]*(ls|id|pwd|wget)"
 
</IfModule>
Back to top
raffe



Joined: 20 Dec 2005
Posts: 15

PostPosted: Tue 27 Dec '05 22:56    Post subject: Reply with quote

I replaced the standard rules with yours, then Apache didnt want to start (copy - paste). How come?

Today I use http://www.wampserver.com/en/download.php on WinXP:
- Includes MySQL 5.0 and the mysqli extension, mysql connections are opened with mysqli_connect()
- Apache 2.0.55
- PHP 5.1.1 + PECL
- SQLitemanager
- MySQL 5.0.17
- Phpmyadmin


These are the standard rules I use now (I know I should change the rules, but don't know enough, don't even have this file exec:/home/users/ivanr/apache/bin/report-attack.pl Embarassed )
Quote:
<IfModule mod_security.c>
# Turn module advertising On or Off
# SecServerResponseToken On

# Turn the filtering engine On or Off
SecFilterEngine On

# Make sure that URL encoding is valid
SecFilterCheckURLEncoding On

# Only allow bytes from this range
SecFilterForceByteRange 32 126

# The audit engine works independently and
# can be turned On of Off on the per-server or
# on the per-directory basis. "On" will log everything,
# "DynamicOrRelevant" will log dynamic requests or violations,
# and "RelevantOnly" will only log policy violations
SecAuditEngine RelevantOnly

# The name of the audit log file
SecAuditLog logs/audit_log

SecFilterDebugLog logs/modsec_debug_log
SecFilterDebugLevel 0

# Should mod_security inspect POST payloads
SecFilterScanPOST On

# Action to take by default
SecFilterDefaultAction "deny,log,status:500"

# Redirect user on filter match
SecFilter xxx redirect:http://www.webkreator.com

# Execute the external script on filter match
SecFilter yyy log,exec:/home/users/ivanr/apache/bin/report-attack.pl

# Simple filter
SecFilter 111

# Only check the QUERY_STRING variable
SecFilterSelective QUERY_STRING 222

# Only check the body of the POST request
SecFilterSelective POST_PAYLOAD 333

# Only check arguments (will work for GET and POST)
SecFilterSelective ARGS 444

# Test filter
SecFilter "/cgi-bin/modsec-test.pl/keyword"

# Another test filter, will be denied with 404 but not logged
# action supplied as a parameter overrides the default action
SecFilter 999 "deny,nolog,status:500"

# Prevent OS specific keywords
SecFilter /etc/passwd

# Prevent path traversal (..) attacks
SecFilter "\.\./"

# Weaker XSS protection but allows common HTML tags
SecFilter "<[[:space:]]*script"

# Prevent XSS atacks (HTML/Javascript injection)
SecFilter "<(.|\n)+>"

# Very crude filters to prevent SQL injection attacks
SecFilter "delete[[:space:]]+from"
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"

# Require HTTP_USER_AGENT and HTTP_HOST headers
SecFilterSelective "HTTP_USER_AGENT|HTTP_HOST" "^$"

# Forbid file upload
SecFilterSelective "HTTP_CONTENT_TYPE" multipart/form-data

# Only watch argument p1
SecFilterSelective "ARG_p1" 555

# Watch all arguments except p1
SecFilterSelective "ARGS|!ARG_p2" 666

# Only allow our own test utility to send requests (or Mozilla)
SecFilterSelective HTTP_USER_AGENT "!(mod_security|mozilla)"

# Do not allow variables with this name
SecFilterSelective ARGS_NAMES 777

# Do now allow this variable value (names are ok)
SecFilterSelective ARGS_VALUES 888

# Test for a POST variable parsing bug, see test #41
SecFilterSelective ARG_p2 AAA

# Stop spamming through FormMail
# note the exclamation mark at the beginning
# of the filter - only requests that match this regex will
# be allowed
<Location /cgi-bin/FormMail>
SecFilterSelective "ARG_recipient" "!@webkreator.com$"
</Location>

# when allowing upload, only allow images
# note that this is not foolproof, a determined attacker
# could get around this
<Location /fileupload.php>
SecFilterInheritance Off
SecFilterSelective POST_PAYLOAD "!image/(jpeg|bmp|gif)"
</Location>

</IfModule>
Back to top
Steffen
Moderator


Joined: 15 Oct 2005
Posts: 3049
Location: Hilversum, NL, EU

PostPosted: Tue 27 Dec '05 23:12    Post subject: Reply with quote

Should work, Any error message ?

Try to start apache in a DOS box and see if you get a error message.

Indeed, the example in the Readme First of the .zip not that good, I removed it now from the zip and replaced with an other.


Steffen
Back to top
raffe



Joined: 20 Dec 2005
Posts: 15

PostPosted: Tue 27 Dec '05 23:45    Post subject: Reply with quote

Hi!

Ehh Confused I tried again, and got the same problem when I restarted the apache server as before (and nothing in apache_error.log). Suddenly after the second time I tried to restart (if it don't work the first time, look suprised and try again wihout changing anything Wink ) I got the Windows dialog "The Apache server has got a problem bla bla... Do you like to send an Error report to Microsoft?"

After that it works OK with your rules Rolling Eyes ... Strange Shocked ... I have restarted several times and nothing wrong now (feeling kind of stupid Crying or Very sad )

Or, really, I am happy it works Razz (but, still, very strange). Is this "normal" with Apache?...

Can I use your rules without getting problems (for an example, I don't have phpBB installed)? Or is the new one in the zip better? This one is the new one, is'nt it?:
Quote:
<IfModule mod_security.c>

# Enable ModSecurity
SecFilterEngine On

# Reject requests with status 403
SecFilterDefaultAction "deny,log,status:403"

# Some sane defaults
#SecFilterScanPOST On
SecFilterCheckURLEncoding On
SecFilterCheckUnicodeEncoding Off

# Accept almost all byte values
SecFilterForceByteRange 1 255

# Server masking is optional
# SecServerSignature "Microsoft-IIS/5.0"

# Designate a directory for temporary files
# storage. It is a good idea to change the
# value below to a private directory, just as
# an additional measure against race conditions
#SecUploadDir /tmp
#SecUploadKeepFiles Off

# Only record the interesting stuff
SecAuditEngine RelevantOnly
# Uncomment below to record responses with unusual statuses
# SecAuditLogRelevantStatus ^5
SecAuditLog logs/audit_log

# You normally won't need debug logging
#SecFilterDebugLevel 0
#SecFilterDebugLog logs/modsec_debug_log

# Only accept request encodings we know how to handle
# we exclude GET requests from this because some (automated)
# clients supply "text/html" as Content-Type
SecFilterSelective REQUEST_METHOD "!^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Type "!(^application/x-www-form-urlencoded$|^multipart/form-data;)"

# Do not accept GET or HEAD requests with bodies
SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Length "!^$"

# Require Content-Length to be provided with
# every POST request
SecFilterSelective REQUEST_METHOD "^POST$" chain
SecFilterSelective HTTP_Content-Length "^$"

# Don't accept transfer encodings we know we don't handle
SecFilterSelective HTTP_Transfer-Encoding "!^$"

</IfModule>
Back to top
raffe



Joined: 20 Dec 2005
Posts: 15

PostPosted: Wed 28 Dec '05 0:16    Post subject: Re: Hardening rules for mod_security Reply with quote

Steffen wrote:
When you get false positives for your server, let us know here.
I think I have one. I have PsychoStats on my server, and if I first click on a player and then click on a weapon (to get statistics about that weapon) I get a URL similar to this:
http://cstrike.vnet.ee/stats/player.php?id=201302&weaponid=8&wsort=kills&worder=desc#hitbox

But on my server, if I click that URL I get:
"Forbidden. You don't have permission to access /stats/player.php on this server"

In apache_error.log i get
Quote:
[Tue Dec 27 23:00:47 2005] [error] [client 192.168.0.1] mod_security: Access denied with code 403. Pattern match "^(uname|id|ls|rm|kill)" at ARGS_VALUES("wsort") [msg "Command execution attack"] [hostname "12.34.56.78"] [uri "/stats/player.php?id=33&weaponid=8&wsort=kills&worder=desc"]


I guess it has to do with this line in httpd.conf:
SecFilterSelective ARGS_VALUES "^(uname|id|ls|rm|kill)"

And it finds "...wsort=kills&worder..." (or something, I'm only guessing Wink )

How can we fix this, without taking away the good SecFilterSelective line (I'm sure it is good to have there)... Can we somehow add that "kills" is OK but not "kill"?
Back to top
Steffen
Moderator


Joined: 15 Oct 2005
Posts: 3049
Location: Hilversum, NL, EU

PostPosted: Wed 28 Dec '05 0:26    Post subject: Reply with quote

Good catch.

It is a matter of adjusting the rules to your configuration.

Best is to remove the "kill" :
SecFilterSelective ARGS_VALUES "^(uname|id|ls|rm)"


What you can also do is, not to deny but only logging:

Change:
SecFilterSignatureAction "log,deny,msg:'Command execution attack'"

To:
SecFilterSignatureAction "log,pass,msg:'Command execution attack'"

Steffen
Back to top
raffe



Joined: 20 Dec 2005
Posts: 15

PostPosted: Wed 28 Dec '05 0:37    Post subject: Reply with quote

Q1: Is it possible to do both? something like this?
Code:

...
...
## -- Command execution --------------------
## REMOVE "kill" HERE (to work with Psychostats)
SecFilterSignatureAction "log,deny,msg:'Command execution attack'"

SecFilterSelective ARGS_VALUES "^(uname|id|ls|rm)"
SecFilterSelective ARGS_VALUES "^(ls|id|pwd|wget)"
SecFilterSelective ARGS_VALUES ";[[:space:]]*(ls|id|pwd|wget)"

## PUT "kill" BACK HERE (we will still logg "kill")
SecFilterSignatureAction "log,pass,msg:'Psychostats .wsort=kills. & .v=kills. = OK, Else command execution attack'"

SecFilterSelective ARGS_VALUES "^(kill)"

</IfModule> 


I mean, move kill to another place?

Q2: You write both "ARGS_VALUES" and "ARG_VALUES" above, do the "ARG_VALUES" line mean it belongs to the line above it?


Last edited by raffe on Wed 28 Dec '05 15:56; edited 2 times in total
Back to top
Steffen
Moderator


Joined: 15 Oct 2005
Posts: 3049
Location: Hilversum, NL, EU

PostPosted: Wed 28 Dec '05 1:03    Post subject: Reply with quote

Q1
A good idea to split them.

Q2.
I do not know if there is a diffenrence between ARGS_VALUES and ARG_VALUES . The documentation has also no clue.

I got the rule from the author of mod_security. I asked him if there is a difference. As soon I have an answer I let you know.

Steffen
Back to top
Steffen
Moderator


Joined: 15 Oct 2005
Posts: 3049
Location: Hilversum, NL, EU

PostPosted: Wed 28 Dec '05 15:09    Post subject: Reply with quote

The answer from Ivan is:

ARG_VALUES is an error. It's supposed to say ARGS_VALUES in both places.


Steffen
Back to top


Reply to topic   Topic: Hardening rules for mod_security View previous topic :: View next topic
Post new topic   Forum Index -> How-to's & Documentation & Tips