Experiencing a Security Breach?

24 Hour Hotline: +1 (866) 659-9097 Option 5

General

+1 (312) 873-7500

Monday - Friday 8:00 AM - 6:00 PM CT (UTC -6)

Sales

Contact a Trustwave solution specialist.

+1 (888) 878-7817

Monday - Friday 8:30 AM - 5:30 PM CT (UTC -6)

Loading...

Blogs & Stories

SpiderLabs Blog

Attracting more than a half-million annual readers, this is the security community's go-to destination for technical breakdowns of the latest threats, critical vulnerability disclosures and cutting-edge research.

Advanced Topic of the Week: XSS Defense via Content Injection

Introduction

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.

Concept

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.

Content Injection Directives and Variable Usage

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).

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).

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:

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:

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:

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

Conclusion

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