ModSecurity Trustwave
This blog has moved! Please update your
bookmarks to

ModSecurity Blog: September 2010

Advanced Topic of the Week: XSS Defense via Content Injection


In last week's post on Identifying Improper Output Handling, we showed a method to use ModSecurity to identify if client request data is echoed back in html responses thus identifying a potential XSS vector.  While this can prove useful to a large chunk of XSS flaws, it is not foolproof as there are many scenarios where the inbound data is altered slightly by the application and thus turns a benign payload into something executable (see the Giorgio Maone's Lost in Translation post for a perfect example with ASP classic).  In this situation, the example rules to identify improper output handling wouldn't have matched...

There is a lot a WAF can do with outbound traffic to help protect web applications from information leakages. There has not been as much progress made, however, in analyzing, manipulating or adding data to outbound dynamic code being sent from the web application to the clients. This is the concept that I want to discuss today.


Previous versions of ModSecurity did not alter any of the actual transactional data (either inbound or outbound). ModSecurity would make copies of the data, place it into memory and then apply all data transformations, etc... and it would then decide what disruptive action to take if there was a rule match on the data. While this process works well in defense of the vast majority of web application security issues, there are still certain situations where it is limited.

Client-side security issues are difficult to address in this architecture since the WAF has no visibility on the client (inside the DOM of the browser). With the new Content Injection capabilities in ModSecurity, we have added two actions which will allow ModSecurity rule writers to either "prepend" or "append" any text data to text-based (html) outbound data content.

The really useful idea is to inject a JavaScript fragment at the top of all outgoing HTML pages. The advantage of using ModSecurity's Content Injection approach is that you can be assured that your code runs prior to any other user-supplied code that is leveraging an XSS flaw.  For example you could detect JavaScript code in places where it is not expected, look for weird HTML/JavaScript code indicative of attacks, remove external links, and so on. While full support for DOM manipulation on the server is not available yet, ModSecurity does support content injection, where you can inject stuff at the beginning or at the end of the page. The original idea behind this this feature was to make DOM XSS detection possible within the client browser. The idea is to inject a chunk of JavaScript to analyse the request URI from inside the browser to detect attacks.

Some other use-case ideas for Injecting code by using a WAF:

  • Ensure complex, dynamic behaviour independent of the application, including obfuscation & polymorphism.

  • Continues updates and potentially even an “in the cloud” service.

  • Provide protection for non-HTML pages by wrapping them in HTML (redirect, refresh, frames).

You could also use it to help secure session management:

  • Avoid the evasion options of Cookies & HTTP authentication (Amit Klein, “Path Insecurity”)

  • Perform implicit authentication to use to prevent session hijacking.

  • One time tokens “super” digest authentication.

Intercept JavaScript Events to perform:

  • Client side input validation (Amit Klein, “DOM Based Cross Site Scripting or XSS of the Third Kind”).

  • DOM Hardening and Anomaly Detection.

  • Rules/Signature based negative security.

Content Injection Directives and Variable Usage

Description: Enables content injection using actions append and prepend.

Syntax: SecContentInjection (On|Off)

Example Usage: SecContentInjection On

Version: 2.5.0

Description: Appends text given as parameter to the end of response body. For this action to work content injection must be enabled by setting SecContentInjection to On. 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).

Action Group: Non-Disruptive

Processing Phases: 3 and 4.


SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,pass,append:'<hr>Footer'"

Description: Prepends text given as parameter to the response body. For this action to work content injection must be enabled by setting SecContentInjection to On. 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).

Action Group: Non-Disruptive

Processing Phases: 3 and 4.


SecRule RESPONSE_CONTENT_TYPE ^text/html "phase:3,nolog,pass,prepend:'Header<br>'"

Testing Injection Rules

Let's run a quick test with the following ruleset:

SecContentInjection On
SecDefaultAction "log,deny,phase:2,status:500,t:none,setvar:tx.alert=1"
SecRule TX:ALERT "@eq 1" "phase:3,nolog,pass,chain,prepend:'<script>alert(\"Why Are You Trying To Hack My Site?\")</script>'"
SecRule RESPONSE_CONTENT_TYPE "^text/html"

This rule set enables the Content Injection capabilities an then sets a default action. The important point to see on the SecDefaultAction line is the "setvar:tx.alert=1" action. What this will do is set a transactional variable if any of the rules trigger a match. The last two lines of the configuration are a chained rule set that runs in phase:3. The first part of the chain will simply look for the "alert" tx variable. If it is set, that means that the client's request has triggered one of the ModSecurity rules and is thus some form of attack. The second part of the rule then makes sure that the response data is of the correct content type (text/html). If so, this rule will then insert some javascript that will issue an alert pop-up box asking them why they are trying to hack the web site :)

Let's take a look at the modsec_debug.log file to see exactly how this new operator is functioning:

# cat modsec_debug.log | sed "s/^.*\[.\] //g" |less
Initialising transaction (txid CP2J2cCoD4QAAF2eAj8AAAAA).
Adding request argument (QUERY_STRING): name "param", value "<script>document.write('<img src=\"http://' document.cookie '\"')</script>"
Transaction context created (dcfg 95da848).
Starting phase REQUEST_BODY.
This phase consists of 85 rule(s).
Recipe: Invoking rule 9654a98; [file "/usr/local/apache/conf/rules/modsecurity_crs_15_customrules.conf" ] [line "15"] [id "1"].
Rule 9654a98: SecRule "ARGS" "(?:\\b(?:(?:type\\b\\W*?\\b(?:text\\b\\W*?\\b(?:j(?:ava)?|ecma|vb)|applic ation\\b\\W*?\\bx-(?:java|vb))script|c(?:opyparentfolder|reatetextrange)|get(?:special|parent)folder)\\ b|on(?:(?:mo(?:use(?:o(?:ver|ut)|down|move|up)|ve)|key(?:press|down|up)|c(?:hange|lick)|s(?:elec|ubmi)t |(?:un)?load|dragdrop|resize|focus|blur)\\b\\W*?=|abort\\b)|(?:l(?:owsrc\\b\\W*?\\b(?:(?:java|vb)script |shell)|ivescript)|(?:href|url)\\b\\W*?\\b(?:(?:java|vb)script|shell)|background-image|mocha):|s(?:(?:t yle\\b\\W*=.*\\bexpression\\b\\W*|ettimeout\\b\\W*?)\\(|rc\\b\\W*?\\b(?:(?:java|vb)script|shell|http):) |a(?:ctivexobject\\b|lert\\b\\W*?\\())|<(?:(?:body\\b.*?\\b(?:backgroun|onloa)d|input\\b.*?\\btype\\b\\ W*?\\bimage|script|meta)\\b|!\\[cdata\\[)|(?:\\.(?:(?:execscrip|addimpor)t|(?:fromcharcod|cooki)e|inner html)|\\@import)\\b)" "capture,t:htmlEntityDecode,t:lowercase,ctl:auditLogParts=+E,log,auditlog,msg:'Cr oss-site Scripting (XSS) Attack. Matched signature <%{TX.0}>',id:'1',severity:'2'"
Expanded "ARGS" to "ARGS:param".
CACHE: Enabled
CACHE: Fetching ARGS:param 1;htmlEntityDecode
CACHE: Caching 1;htmlEntityDecode="<script>document.write('<img src="' docum ent.cookie '"')</script>"
T (0) htmlEntityDecode: "<script>document.write('<img src="' document.cookie '"')</script>"
CACHE: Fetching ARGS:param 2;htmlEntityDecode,lowercase
CACHE: Caching 2;htmlEntityDecode,lowercase="<script>document.write('<img src=" 00/' document.cookie '"')</script>"
T (0) lowercase: "<script>document.write('<img src="' document.cookie '"')</ script>"
Executing operator "rx" with param "(?:\\b(?:(?:type\\b\\W*?\\b(?:text\\b\\W*?\\b(?:j(?:ava)?|ecma|vb)| application\\b\\W*?\\bx-(?:java|vb))script|c(?:opyparentfolder|reatetextrange)|get(?:special|parent)fol der)\\b|on(?:(?:mo(?:use(?:o(?:ver|ut)|down|move|up)|ve)|key(?:press|down|up)|c(?:hange|lick)|s(?:elec| ubmi)t|(?:un)?load|dragdrop|resize|focus|blur)\\b\\W*?=|abort\\b)|(?:l(?:owsrc\\b\\W*?\\b(?:(?:java|vb) script|shell)|ivescript)|(?:href|url)\\b\\W*?\\b(?:(?:java|vb)script|shell)|background-image|mocha):|s( ?:(?:tyle\\b\\W*=.*\\bexpression\\b\\W*|ettimeout\\b\\W*?)\\(|rc\\b\\W*?\\b(?:(?:java|vb)script|shell|h ttp):)|a(?:ctivexobject\\b|lert\\b\\W*?\\())|<(?:(?:body\\b.*?\\b(?:backgroun|onloa)d|input\\b.*?\\btyp e\\b\\W*?\\bimage|script|meta)\\b|!\\[cdata\\[)|(?:\\.(?:(?:execscrip|addimpor)t|(?:fromcharcod|cooki)e |innerhtml)|\\@import)\\b)" against ARGS:param.
Target value: "<script>document.write('<img src="' document.cookie '"')</scr ipt>"
Added regex subexpression to TX.0: <script
Operator completed in 805 usec.
Setting variable: tx.alert=1
Set variable "tx.alert" to "1".
Ctl: Set auditLogParts to ABIEFHZE.
Rule returned 1.
Match, intercepted -> returning.
Resolved macro %{TX.0} to "<script"
Access denied with code 500 (phase 2). Pattern match "(?:\b(?:(?:type\b\W*?\b(?:text\b\W*?\b(?:j(?:ava) ?|ecma|vb)|application\b\W*?\bx-(?:java|vb))script|c(?:opyparentfolder|reatetextrange)|get(?:special|pa rent)folder)\b|on(?:(?:mo(?:use(?:o(?:ver|ut)|down|move|up)|ve)|key(?:press|down|up)|c(?:hange|lick) .. ." at ARGS:param. [file "/usr/local/apache/conf/rules/modsecurity_crs_15_customrules.conf"] [line "15"] [id "1"] [msg "Cross-site Scripting (XSS) Attack. Matched signature <<script>"] [severity "CRITICAL"]
Time #2: 14304
Hook insert_error_filter: Adding output filter (r 9747ca0).
Output filter: Receiving output (f 9749ac8, r 9747ca0).
Starting phase RESPONSE_HEADERS.
This phase consists of 1 rule(s).
Recipe: Invoking rule 9653e90; [file "/usr/local/apache/conf/rules/modsecurity_crs_15_customrules.conf" ] [line "6"].
Rule 9653e90: SecRule "TX:ALERT" "@eq 1" "phase:3,log,pass,chain,prepend:'<script>alert(\"Why Are You T rying To Hack My Site?\")</script>'"
Expanded "TX:ALERT" to "TX:alert".
CACHE: Disabled - TX:alert value length=1, smaller than minlen=15
Executing operator "eq" with param "1" against TX:alert.
Target value: "1"
Operator completed in 711 usec.
Setting variable: tx.alert=1
Set variable "tx.alert" to "1".
Rule returned 1.
Match -> mode NEXT_RULE.
Recipe: Invoking rule 9654380; [file "/usr/local/apache/conf/rules/modsecurity_crs_15_customrules.conf" ] [line "7"].
Rule 9654380: SecRule "RESPONSE_CONTENT_TYPE" "^text/html"
CACHE: Enabled
Executing operator "rx" with param "^text/html" against RESPONSE_CONTENT_TYPE.
Target value: "text/html; charset=iso-8859-1"
Operator completed in 13 usec.
Setting variable: tx.alert=1
Set variable "tx.alert" to "1".
Warning. Pattern match "^text/html" at RESPONSE_CONTENT_TYPE. [file "/usr/local/apache/conf/rules/modse curity_crs_15_customrules.conf"] [line "6"]
Rule returned 1.
Match -> mode NEXT_RULE.
Content Injection: Removing headers (C-L, L-M, Etag, Expires).
Output filter: Bucket type HEAP contains 535 bytes.
Output filter: Bucket type EOS contains 0 bytes.
Output filter: Completed receiving response body (buffered full - 535 bytes).


XSS Defense Use-Case Example: Active Content Signatures (ACS)

Now that we have a mechanism for adding Javascript to outbound responses, which will allow us access into the browser environment, the next question is: what data do we add?  After some independent research, including the OWASP Encoding Project and Google-Caja's html_sanitizer.js I decided to reach out to some fellow web security folks (Mario Heiderich and Stefano Di Paola) who lead me to Eduardo Vela's Active Content Signatures (ACS) Project.  Bingo!  This is the intro section from Eduardo's ACS PDF:

One of the main challenges in secure web application development is how to mix user supplied content and the server content. This, in its most basic form has created one ofthe most common vulnerabilities now a days that affect most if not all websites in the web, the so called Cross Site Scripting (XSS).

A good solution would be a technology capable of limiting the scope of XSS attacks, by a way to tell the browser what trusted code is, and what is not. This idea has been out for ages, but it has always required some sort of browser native support.  ACS (Active Content Signature) comes to solve this problem, by creating a JavaScript code that will work in all browsers, without the need to install anything, and that will completely remove from the DOM any type of dangerous code.

I will start by demonstrating how ACS solves XSS issues, without the need ofthe server to do any type of parsing or filtering, and without endangering the user.  ACS will be appended at the beginning of the webpage's HTML code. As a simple external JavaScriptcode, something like:

<html><head><script type="text/javascript" src="/acs.js">/*signaturehere*/<plaintext/></script>

When this script is loaded, it will automatically stop the parsing of the rest ofthe HTML page. It will, then recreate the DOM itself, taking out dangerous snippets of code (like event handlers,or scripts), making the browser display it's content's without any danger.  Now, if the user wants to make exceptions so their own scripts are loaded,they can do so, ina very simple way... adding a signature.

After discussing my goals with Eduardo and working through some tests, we came up with a working proof of concept integration using ModSecurity's Content Injection capabilities to prepend the ACS JS code to the top of selected web pages.  The advantage of this approach is that you don't have to alter the html source of any of your pages, as ModSecurity will prepend this data for you on the fly.    

Here is what you need to test out this concept:

  • Download the ACS JS file from Eduardo's site and place it in your site's DocumentRoot as clients will need to access this file when our injected JS executes.
  • Download the localized ACS file from the ModSecurity site and place it within your DocumentRoot as well as the clients will also need to access this file.  This is the file that creates the temporary DOM, validates/allows the authorized JS to run on your site and then recreates the DOM.  You will need to update the "default-src" regular expression to allow JS to run from authorized domains (such as Google Analytics, 3rd party sites, etc...)
  • Add the following ModSecurity directives/rules to your ModSecurity configuration:
SecContentInjection On
SecRule RESPONSE_CONTENT_TYPE "^text/html" "phase:4,t:none,nolog,prepend:'<html><head><script type=\"text/javascript\" src=\"/acs.js\"></script><script type=\"text/javascript\" src=\"/xss.js\"></script>'"

In order to help facilitate community testing of this proof of concept, we have created an online demo.  We encourage the community to help test this implementation to help identify any evasions or bugs.  You can toggle on/off the XSS Defense to ensure that your payload executes and then continue testing with the defense in place.

Current Limitations

  • The current implementation of ACS does not allow for inline scripts, so web pages would need to be re-written to reference external src files.
  • There are still browser quirks that cause parsing errors in the new DOM rendered by ACS (surprise, surprise in IE...)
  • The blacklist tags in the ACS code still need to be expanded


We hope that this concept helps to provide a layered defense for XSS issues and to show yet another advanced feature of ModSecurity!

Advanced Topic of the Week: Identifying Improper Output Handling (XSS Flaws)

A Topic Presents Itself

As I sat down this morning thinking about an appropriate topic for this week's blog post, I quickly found my subject - XSS flaws.  The Twitter-verse exploded this morning with an outbreak of an XSS worm that is using the onmouseover event to propagate itself (technically I believe that this is a CSRF attack as it is forcing the user to send a Twitter update that they didn't intend to send... but I digress.).  I quickly added this incident into the WASC Web Hacking Incident Database.

How Prevalent is XSS?

Just how big of a problem is XSS?  Most web application security statistics projects have it listed right at the top -

OWASP Top 10 Web Application Security Risks for 2010

WASC Web Application Security Statistics 

WASC Web Hacking Incident Database

How Can You Protect Yourself?

First of all, make sure that all of your developers read, then reread, and then really sit down and take notes and seriously get a game plan together to address the issues raised in the OWASP XSS Prevention Cheatsheet document.  Make sure you understand this section on untrusted data:

Untrusted data is most often data that comes from the HTTP request, in the form of URL parameters, form fields, headers, or cookies. But data that comes from databases, web services, and other sources is frequently untrusted from a security perspective. That is, it might not have been perfectly validated. The OWASP Code Review Guide has a decent list of methods that return untrusted data in various languages, but you should be careful about your own methods as well.

Untrusted data should always be treated as though it contains an attack. That means you should not send it anywhere without taking steps to make sure that any attacks are detected and neutralized. As applications get more and more interconnected, the likelihood of a buried attack being decoded or executed by a downstream interpreter increases rapidly.

Traditionally, input validation has been the preferred approach for handling untrusted data. However, input validation is not a great solution for injection attacks. First, input validation is typically done when the data is received, before the destination is known. That means that we don't know which characters might be significant in the target interpreter. Second, and possibly even more importantly, applications must allow potentially harmful characters in. For example, should poor Mr. O'Malley be prevented from registering in the database simply because SQL considers ' a special character?

The OWASP ModSecurity Core Rule Set (CRS) contains many rules to try and identify malicious XSS payloads for example in the modsecurity_crs_41_xss_attacks.conf file.  The XSS payload used in the Twitter attacks today have been posted to PasteBin and if you send it to the CRS Demo you will see that it is detected by many different detection methods.

While input validation and looking for generic attack payloads is useful for identifying attack attempts, it is not the same as identifying the actual underlying application weakness that is exploited by XSS attacks and that is Improper Output Handling.  Essentially, what you need is Dynamic Taint Propagation detection where you can track where unstrusted user data is insecurely used within your application.  For XSS you need to identify where user supplied data is echoed back to clients in an unescaped form.

Dynamic Taint Propagation with ModSecurity

In CRS v2.0.7, we added an optional ruleset called modsecurity_crs_55_application_defects.conf which, among other things, implements an experimental dynamic taint propagation ruleset to identity if/when/where an application does not properly output encode/escape user supplied data.

# XSS Detection - Missing Output Encoding
SecAction "phase:1,nolog,pass,initcol:global=xss_list"

# Identifies Reflected XSS
# If malicious input (with Meta-Characters) is echoed back in the reply non-encoded.
SecRule &ARGS "@gt 0" "chain,phase:4,t:none,log,auditlog,deny,status:403,id:'1',msg:'Potentially Malicious Meta-Characters in User Data Not Properly Output Encoded.',logdata:'%{tx.inbound_meta-characters}'"
 	SecRule ARGS "([\'\"\(\)\;<>#])" "chain,t:none"
		SecRule MATCHED_VAR "^.{15,}$" "chain,t:none,setvar:tx.inbound_meta-characters=%{matched_var}"
  			SecRule RESPONSE_BODY "@contains %{tx.inbound_meta-characters}" "ctl:auditLogParts=+E"

# Check to see if TX XSS Data is already in the GLOBAL list.  If it is - expire it.
SecRule GLOBAL:'/XSS_LIST_.*/' "@streq %{tx.inbound_meta-characters}" "phase:4,t:none,nolog,pass,skip:1"
SecRule TX:INBOUND_META-CHARACTERS ".*" "phase:4,t:none,nolog,pass,setvar:global.xss_list_%{time_epoch}=%{matched_var}"
# Identifies Stored XSS
# If malicious input (with Meta-Characters) is echoed back on any page non-encoded.
SecRule GLOBAL:'/XSS_LIST_.*/' "@within %{response_body}" "phase:4,t:none,log,auditlog,pass,msg:'Potentially Malicious Meta-Characters in User Data Not Properly Output Encoded',tag:'WEB_ATTACK/XSS'"

Keep in mind - this ruleset's goal is not to try and identify malicious payloads but rather to indirectly identify possible stored/reflected XSS attack surface points by flagging when an application resources does not properly output escape user supplied data.  An advantage to this approach is that we don't have to be as concerned with evasion issues as they rules are not looking for malicious payloads.  Instead, they will monitor as normal users interact with the application and will alert if the application does not correctly handle the data.

Using this type of application weakness detection, it is possible to identify the underlying issues in the application and get a plan together to address them rather than perpetually playing "Whack-a-Mole" with inbound attacks.

Advanced Topic of the Week: Validating SessionIDs

This week's topic discusses how to validate application SessionIDs submitted by clients.

Reference Manual

Initializing the SESSION collection with the setsid action.


Description: Special-purpose action that initialises the SESSION collection.

Action Group: Non-disruptive


# Initialise session variables using the session cookie value 


On first invocation of this action the collection will be empty (not taking the predefined variables into account - see initcol 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 SESSIONID 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.


This variable is a collection, available only after setsid 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.

SecRule REQUEST_URI "^/cgi-bin/foo" \
SecRule SESSION:SCORE "@gt 50" "pass,log,setvar:session.blocked=1"
SecRule SESSION:BLOCKED "@eq 1" "log,deny,status:403"

OWASP ModSecurity CRS

The OWASP ModSecurity CRS includes an example ruleset that will validate SessionIDs as part of the optional_rules/modsecurity_crs_43_csrf_protection.conf file.  

# This rule will identify the outbound Set-Cookie SessionID data and capture it in a setsid
SecRule RESPONSE_HEADERS:/Set-Cookie2?/ "(?i:(j?sessionid|(php)?sessid|(asp|jserv|jw)?session[-_]?(id)?|cf(id|token)|sid)=([^\s]+)\;\s?)" "chain,phase:3,t:none,pass,nolog,capture,setsid:%{TX.6},setvar:session.sessionid=%{TX.6},setvar:session.valid=1"
    SecRule SESSION:SESSIONID "(.*)" "t:none,t:sha1,t:hexEncode,capture,setvar:session.csrf_token=%{TX.1}"

# This rule file will identify outbound Set-Cookie/Set-Cookie2 response headers and
# then initiate the proper ModSecurity session persistent collection (setsid).
# The rules in this file are required if you plan to run other checks such as
# Session Hijacking, Missing HTTPOnly flag, etc...

# This rule set will identify subsequent SessionIDs being submitted by clients in
# Request Headers. First we check that the SessionID submitted is a valid one

SecRule REQUEST_COOKIES:'/(j?sessionid|(php)?sessid|(asp|jserv|jw)?session[-_]?(id)?|cf(id|token)|sid)/' ".*" "chain,phase:1,t:none,pass,nolog,auditlog,msg:'Invalid SessionID Submitted.',setsid:%{matched_var},setvar:tx.sessionid=%{matched_var},skipAfter:END_SESSION_STARTUP"
    SecRule SESSION:VALID "!@eq 1" "t:none"

SecAction "phase:1,t:none,nolog,pass,setuid:%{session.username},setvar:session.sessionid=%{tx.sessionid}"


Further description of this ruleset is discussed below.

So What?

Why should you try and validate SessionIDs sent by clients?  I am reminded of President Ronald Reagan's famous saying "Trust, But Verify."  Put it this way, just because a client sends a SessionID within the Request Header Cookie data does not mean that it is a valid one.  There are numerous attacks where malicious clients will send in bogus SessionIDs with the most prevalent one being Credential/Session Prediction where an attacker manipulates the SessionID data in hopes that they can achieve a Session Hijacking attack.  Another attack scenario that was just recently identified is the 'Padding Oracle' Crypto Attack against ASP.Net applications where the attacker sends in bogus encrypted SessionID.  Based on the errors sent back out my the application they may be able to identify the crypto keys which would allow them to possibly decrypt sniffed cookie data or forge tickets.

The key concept with mitigating these types of SessionID attacks is to simply ask yourself - Do you trust the client or the application?  The critical security moment in identifying many application session attacks is to initiate session collection data only when the application hands out a SessionID in a Set-Cookie response header.  If you use the ModSecurity setsid action at this point, you can then also set a new variable within the collection to mark the SessionID as "valid" meaning that it is one that application actually handed out to a client.  With this Session collection data saved, you can then use validation rules that will extract out any SessionID data submitted by client within Request Header Cookie data and verify if the "valid" variable has been sent.  If this variable is not present, then you know that the client is sending a bogus SessionID.

WASC WHID Bi-Annual Report for 2010

The Web Hacking Incident Database (WHID) is a project dedicated to maintaining a record of web application-related security incidents. WHID’s purpose is to serve as a tool for raising awareness of web application security problems and to provide information for statistical analysis of web application security incidents. Unlike other resources covering web site security – which focus on the technical aspect of the incident – the WHID focuses on the impact of the attack. Trustwave's SpiderLabs is a WHID project contributor.

Report Summary Findings

An analysis of the Web hacking incidents from the first half of 2010 performed by Trustwave’s SpiderLabs Security Research team shows the following trends and findings:

  • A steep rise in attacks against the financial vertical market is occurring in 2010, and is currently the no. 3 targeted vertical at 12 percent. This is mainly a result of cybercriminals targeting small to medium businesses’ (SMBs) online banking accounts.
  • Corresponding to cybercriminals targeting online bank accounts, the use of Banking Trojans (which results in stolen authentication credentials) made the largest jump for attack methods (Banking Trojans + Stolen Credentials).
  • Application downtime, often due to denial of service attacks, is a rising outcome.
  • Organizations have not implemented proper Web application logging mechanisms and thus are unable to conduct proper incident response to identify and correct vulnerabilities. This resulted in the no. 1 “unknown” attack category.

WHID Top 10 Risks for 2010

As part of the WHID analysis, here is a current Top 10 listing of the application weaknesses that are actively being exploited (with example attack method mapping in parentheses). Hopefully this data can be used by organizations to re-prioritize their remediation efforts.

WHID Top 10 for 2010


Improper Output Handling (XSS and Planting of Malware)


Insufficient Anti-Automation (Brute Force and DoS)


Improper Input Handling (SQL Injection)


Insufficient Authentication (Stolen Credentials/Banking Trojans)


Application Misconfiguration (Detailed error messages)


Insufficient Process Validation (CSRF and DNS Hijacking)


Insufficient Authorization (Predictable Resource Location/Forceful Browsing)


Abuse of Functionality (CSRF/Click-Fraud)


Insufficient Password Recovery (Brute Force)


Improper Filesystem Permissions (info Leakages)

Download the full report and Join the live Trustwave Webinar Sept. 16th: Web Hacking Incidents Revealed: Trends, Stats and How to Defend (registration required).

Advanced Topic of the Week: Real-time Blacklist Lookups

This week's feature is the effective use of Real-time Blacklist lookups (@rbl).

Reference Manual


Description: Look up the parameter in the RBL given as parameter. Parameter can be an IPv4 address, or a hostname.


SecRule REMOTE_ADDR "@rbl"

OWASP ModSecurity CRS

The OWASP ModSecurity CRS includes limited use of the @rbl operator within the optional_rules/modsecurity_crs_42_comments_spam.conf file:

# Comment spam is an attack against blogs, guestbooks, wikis and other types of
# interactive web sites that accept and display hyperlinks submitted by
# visitors. The spammers automatically post specially crafted random comments
# which include links that point to the spammer's web site. The links
# artificially increas the site's search engine ranking and may make the site
# more noticable in search results.

SecRule IP:PREVIOUS_RBL_CHECK "@eq 1" "phase:1,t:none,pass,nolog,skipAfter:END_RBL_LOOKUP"
 SecRule REMOTE_ADDR "@rbl" "phase:1,t:none,pass,nolog,auditlog,msg:'RBL Match for SPAM Source',tag:'AUTOMATION/MALICIOUS',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.automation_score=+%{tx.warning_anomaly_score},setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{}-AUTOMATION/MALICIOUS-%{matched_var_name}=%{matched_var},setvar:ip.spammer=1,expirevar:ip.spammer=86400,setvar:ip.previous_rbl_check=1,expirevar:ip.previous_rbl_check=86400,skipAfter:END_RBL_CHECK"

 SecAction "phase:1.t:none,nolog,pass,setvar:ip.previous_rbl_check=1,expirevar:ip.previous_rbl_check=86400"

SecRule IP:SPAMMER "@eq 1" "phase:1,t:none,pass,nolog,auditlog,msg:'Request from Known SPAM Source (Previous RBL Match)',tag:'AUTOMATION/MALICIOUS',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.automation_score=+%{tx.warning_anomaly_score},setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.%{}-AUTOMATION/MALICIOUS-%{matched_var_name}=%{matched_var}"


The goal of this ruleset is to run an @rbl check once for each IP address and then save the response in a TX variable for 1 day.  This is used to limit the number of @rbl lookups that the web server needs to do as there is a latency hit for executing the DNS queries.

So What?

Why use Real-time Blacklist Lookups anyways?   What we are talking about here is IP Reputation.  Has this client been identified as bad by other web sites?  It is sort of like the "No Fly" lists that the Department of Homeland Security makes available to airlines.  It is a method of sharing information about clients so that you can decided if you want to allow this client access to your site at all or perhaps treat them differently (such as with increased logging).  Real-time block lists (RBL) are community-based, central repositories for IP Reputation. RBLs are most commonly used to identify web-based comment spam. If you run a blog or user-forum site, wouldn't you like to know if the current client has already been identified as a spammer?

While @rbl is a useful feature, there is a caution with its usage - it is a severe performance hit and can cause increased latency for clients.  Whereas the @geoLookup operator accessed a local DB, @rbl checks occur in real-time over the network and utilize the DNS infrastructure.  For the same reason that most web admins disable real-time client resolution in logging, running a DNS lookup on each client request can cause severe delays.  

@rbl Tips

Here are a few recommended tips for using @rbl.

DNS Caching

Implement a local caching DNS server like rbldnsd so that your @rbl checks issue DNS queries to the local system first.

Use ModSecurity Persistent Storage

Alternatively, you can use ModSecurity to save rbl responses in the IP persistent storage collection.  This is what the CRS modsecurity_crs_42_comment_spam.conf file does.  The persistent data is cached for 1 day.

Choose your RBL carefully

Make sure that you choose your RBL carefully.  You not only want to ensure that the RBL category is appropriate for your site but also that the accuracy of the list is good.


November 2010
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30


Atom Feed



Recent Entries