A Codelab by Bruce Leban, Mugdha Bendre, and Parisa Tabriz
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.
viewed by another user, you have an XSS vulnerability. A simple
function, which creates a pop-up box with whatever string you pass as
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
alert(1) then you can inject arbitrary script
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.
Can you upload a file that allows you to execute arbitrary script
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:
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.
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.)
You can also do XSS by injecting a value into an HTML attribute. Inject a script by setting the color value in a profile.
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.
Find a URL that when clicked on will execute a script using one of Gruyere's AJAX features.
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:
© 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>.