Web Application Exploits and Defenses (Part 2)

A Codelab by Bruce Leban, Mugdha Bendre, and Parisa Tabriz

Table of Contents

Cross-Site Scripting (XSS)

Cross-site scripting (XSS) is a vulnerability that permits an attacker to inject code (typically HTML or Javascript) into contents of a website not under the attacker's control. When a victim views such a page, the injected code executes in the victim's browser. Thus, the attacker has bypassed the browser's same origin policy and can steal victim's private information associated with the website in question.

In a reflected XSS attack, the attack is in the request itself (frequently the URL) and the vulnerability occurs when the server inserts the attack in the response verbatim or incorrectly escaped or sanitized. The victim triggers the attack by browsing to a malicious URL created by the attacker. In a stored XSS attack, the attacker stores the attack in the application (e.g., in a snippet) and the victim triggers the attack by browsing to a page on the server that renders the attack, by not properly escaping or sanitizing the stored data.

More details

XSS Challenges

Typically, if you can get Javascript to execute on a page when it's viewed by another user, you have an XSS vulnerability. A simple Javascript function to use when hacking is the alert() function, which creates a pop-up box with whatever string you pass as an argument.

You might think that inserting an alert message isn't terribly dangerous, but if you can inject that, you can inject other scripts that are more malicious. It is not necessary to be able to inject any particular special character in order to attack. If you can inject alert(1) then you can inject arbitrary script using eval(String.fromCharCode(...)).

Your challenge is to find XSS vulnerabilities in Gruyere. You should look for vulnerabilities both in URLs and in stored data. Since XSS vulnerabilities usually involve applications not properly handling untrusted user data, a common method of attack is to enter random text in input fields and look at how it gets rendered in the response page's HTML source. But before we do that, let's try something simpler.

File Upload XSS

Can you upload a file that allows you to execute arbitrary script on the google-gruyere.appspot.com domain?

Hint

Exploit and Fix

Reflected XSS

There's an interesting problem here. Some browsers have built-in protection against reflected XSS attacks. There are also browser extensions like NoScript that provide some protection. If you're using one of those browsers or extensions, you may need to use a different browser or temporarily disable the extension to execute these attacks.

At the time this codelab was written, the two browsers which had this protection were IE and Chrome. To work around this, Gruyere automatically includes a X-XSS-Protection: 0 HTTP header in every response which is recognized by IE and will be recognized by future versions of Chrome. (It's available in the developer channel now.) If you're using Chrome, you can try starting it with the --disable-xss-auditor flag by entering one of these commands:

If you're using Firefox with the NoScript extension, add google-gruyere.appspot.com to the allow list. If you still can't get the XSS attacks to work, try a different browser.

You may think that you don't need to worry about XSS if the browser protects against it. The truth is that the browser protection can't be perfect because it doesn't really know your application and therefore there may be ways for a clever hacker to circumvent that protection. The real protection is to not have an XSS vulnerability in your application in the first place.

Find a reflected XSS attack. What we want is a URL that when clicked on will execute a script.

Hint 1

Hint 2

Exploit and Fix

Stored XSS

Now find a stored XSS. What we want to do is put a script in a place where Gruyere will serve it back to another user.

The most obvious place that Gruyere serves back user-provided data is in a snippet (ignoring uploaded files which we've already discussed.)

Hint 1

Hint 2

Exploit and Fix

Stored XSS via HTML Attribute

You can also do XSS by injecting a value into an HTML attribute. Inject a script by setting the color value in a profile.

Hint 1

Hint 2

Exploit and Fixes

Stored XSS via AJAX

Find an XSS attack that uses a bug in Gruyere's AJAX code. The attack should be triggered when you click the refresh link on the page.

Hint 1

Hint 2

Exploit and Fixes

Reflected XSS via AJAX

Find a URL that when clicked on will execute a script using one of Gruyere's AJAX features.

Hint 1

Hint 2

Exploit and Fixes

More about XSS

In addition to the XSS attacks described above, there are quite a few more ways to attack Gruyere with XSS. Collect them all!

XSS is a difficult beast. On one hand, a fix to an XSS vulnerability is usually trivial and involves applying the correct sanitizing function to user input when it's displayed in a certain context. On the other hand, if history is any indication, this is extremely difficult to get right. US-CERT reports dozens of publicly disclosed XSS vulnerabilities involving multiple companies.

Though there is no magic defense to getting rid of XSS vulnerabilities, here are some steps you should take to prevent these types of bugs from popping up in your products:

  1. First, make sure you understand the problem.
  2. Wherever possible, do sanitizing via templates features instead of calling escaping functions in source code. This way, all of your escaping is done in one place and your product can benefit from security technologies designed for template systems that verify their correctness or actually do the escaping for you. Also, familiarize yourself with the other security features of your template system.
  3. Employ good testing practices with respect to XSS.
  4. Don't write your own template library :)

Continue >>

© Google 2010 Terms of Service
The code portions of this codelab are licensed under the Creative Commons Attribution-No Derivative Works 3.0 United States license <http://creativecommons.org/licenses/by-nd/3.0/us>. Brief excerpts of the code may be used for educational or instructional purposes provided this notice is kept intact. Except as otherwise noted the remainder of this codelab is licensed under the Creative Commons Attribution 3.0 United States license <http://creativecommons.org/licenses/by/3.0/us>.