Firo discovered that any tweet containing a unicode emoji character—such as the heart emoticon ♥ ("♥")—would be treated as raw html (not escaped).
The tweet got itself retweeted 75,811 times before TweetDeck fixed the vulnerability.
Phil walked us through some common XSS vulnerabilities and the steps to mitigate them.
I was surprised to learn that, by default, Sinatra does not escape html. Sinatra is vulnerable to XSS by default.
Phil created this simple Sinatra app to illustrate the Sinatra XSS vulnerability.
<SCRIPT>alert('This site is vulnerable to XSS')</SCRIPT » >
Next, Phil showed us a vulnerable rails app.
By default, Rails will sanitize and/or escape all user-provided input...except for link_to urls.
On Phil's vulnerable rails app, use this GitURL:
Phil gave us the following tips for preventing XSS vulnerabilities:
- Use a templating language that escapes HTML by default
- Always be wary of any user-provided or user-modified fields. Content, URLs, cookies, headers, etc.)
- Know which jQuery methods escape and which don't escape
- Don't roll your own sanitization tools! Use popular tried-and-true libraries.
- Use Content Security Policy (CSP) headers.
Mitigating XSS Risks
He suggested the following tips to reduce XSS risk:
- Force the user to re-enter his password before modifying sensitive data or making a transaction
- Use short session expirations
- Set the HttpOnly flag on cookies
- Limit the content that is shared among users
Here are some resources on XSS:
- Google's XSS Game
- Stripe's Capture the Flag
- Phil's startup GitSentry
- OWASP XSS Cheat Sheet
- Content Security Policy Info
You can see Phil's slides on speakerdeck here.