| 
 
 
 | 
| Keep Server Online 
 If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.
 
 or
 
 
   
 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.
 |  | 
 | 
| | 
| | 
|  Topic: Hardening rules for mod_security |  |  
| Author |  |  
| Steffen Moderator
 
 
 Joined: 15 Oct 2005
 Posts: 3130
 Location: Hilversum, NL, EU
 
 | 
|  Posted: Sun 25 Dec '05 22:08    Post subject: Hardening rules for mod_security |   |  
| 
 |  
| 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
 
 
 | 
|  Posted: Tue 27 Dec '05 22:56    Post subject: |   |  
| 
 |  
| 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
  ) 
  	  | 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: 3130
 Location: Hilversum, NL, EU
 
 | 
|  Posted: Tue 27 Dec '05 23:12    Post subject: |   |  
| 
 |  
| 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
 
 
 | 
|  Posted: Tue 27 Dec '05 23:45    Post subject: |   |  
| 
 |  
| Hi! 
 Ehh
  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  ) 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
  ... Strange  ... I have restarted several times and nothing wrong now (feeling kind of stupid  ) 
 Or, really, I am happy it works
  (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
 
 
 | 
|  Posted: Wed 28 Dec '05 0:16    Post subject: Re: Hardening rules for mod_security |   |  
| 
 |  
| 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: 	  | Steffen wrote: |  	  | When you get false positives for your server, let us know here. | 
 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
  ) 
 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: 3130
 Location: Hilversum, NL, EU
 
 | 
|  Posted: Wed 28 Dec '05 0:26    Post subject: |   |  
| 
 |  
| 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
 
 
 | 
|  Posted: Wed 28 Dec '05 0:37    Post subject: |   |  
| 
 |  
| 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: 3130
 Location: Hilversum, NL, EU
 
 | 
|  Posted: Wed 28 Dec '05 1:03    Post subject: |   |  
| 
 |  
| 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: 3130
 Location: Hilversum, NL, EU
 
 | 
|  Posted: Wed 28 Dec '05 15:09    Post subject: |   |  
| 
 |  
| The answer from Ivan is: 
 ARG_VALUES is an error. It's supposed to say ARGS_VALUES in both places.
 
 
 Steffen
 |  |  
| Back to top |  |  
 
 | 
 |  | 
 |  |