The First, Toughest and Messiest
XSS Filter
Giorgio Maone Ever
giorgio@maone.net
about Giorgio Maone (@ma1)
● Full time dad
about Giorgio Maone (@ma1)
● Full time dad
● NoScript creator & maintainer
● #9 Most Dangerous People on the Internet
● Hackademix breaker + builder
● Mozilla contributor & Sec. Group member
● W3C WASWG invited expert
noscript.net
about NoScript
● JavaScript permission manager
● Embedded content blocker
● Application Boundaries Enforcer (ABE)
● ClearClick (Clickjacking protection)
● HTTPS enhancements
● Usability helpers
● Cross Site Injection Checker
noscript.net
The Injection Checker module
Injection Checker basics
● Hooks cross-site HTTP requests
● Checks document loads
● If triggered, transforms the request
● Sanitizes the document rendering context if
needed
● Notifies user with analyze/bypass options
The Injection Checker module
Hooks cross-site HTTP requests
● https://a.net → https://b.com YES
● http://b.com → https://b.com YES
● https://b.com/a → https://b.com/b NO
● https://a.net → ftp://b.com/ NO
● Navigation bar → https://b.com YES
● External application → https://b.com YES
The Injection Checker module
Hooks cross-site HTTP requests
● Pages reloaded
on Javascript activation! YES
The Injection Checker module
Checks document loads
● HTML pages
● SVG objects
● (I)Frames
● Generic <OBJECT> inclusions
The Injection Checker module
If triggered, transforms the request
● Strips POST payloads from untrusted origins
(rudimentary CSRF protection)
● Sanitizes syntactically valid JavaScript (when
the document to be loaded is allowed)
● Sanitizes potentially dangerous HTML
● Turns suspect POSTs into GETs
The Injection Checker module
Sanitizes the document rendering
context if needed
● Forces UTF-8 if a potentially dangerous and
unusual char-set is found
● Removes potential injections from
window.name
The Injection Checker module
Notifies user with analyze/bypass options
The Injection Checker module
Notifies user with analyze/bypass options
The Injection Checker module
Notifies user with analyze/bypass options
IN MEDIO STAT VIRTUS
THOU SHALL
NOT REINVENT THE WHEEL
ETC. ETC.
The Injection Checker module
Hard blocking + Error page
The Injection Checker module
Imminent changes
● Hooks cross-site HTTP requests
● Checks document loads
● If triggered, transforms suspends the request
● Sanitizes the document rendering context if
needed
● Notifies user with analyze/bypass options
using a “Safe Browsing-like” page
Origins
Once upon a time...
Origins
Whitelist + XSS =
No NoScript
!!!
Origins
Origins
dr.-ing. mario heiderich
Legacy
7 years later...
Legacy
Yeah, right.
Legacy
Firefox has no native protection yet...
Legacy
.. nor has Chrome ;-)
Legacy
did you say MSIE?
Legacy
So where we are, really?
● 2007: NoScript demonstrated client-side XSS
protection was viable
● 2008: MSIE 8's XSS filter (effective against many
attacks but causes vulnerabilities of its own)
● 2010: Chrome's XSS Auditor (weak)
● ????: Firefox's
Heuristics to block reflected XSS (like in IE8)
(TODO, Bug 528661)
experience counts
Credits
NoScript XSS Trainers Hall of Fame
Object.keys(
document.querySelector("#changelog")
.textContent.match(/\n(?:[x+]) .*(\n {2}.*)*/g)
.map(s => let (m = s.match(
/(?:XSS|Inj)[\s\S]*\bthanks\s+(?:to\s+)?\s*([\s\S]+)?\b(?:(?:,\s*)see|for|\))/
)) m && m[1].replace(/\s+/g, ' ').replace(/\s*(?:\bfor\b|\))[\s\S]*|\s+$/g, ''))
.filter(s => !!s)
.reduce((o, s) => s.split(/\s*(?:\band|&|,)\s+/).reduce((o, s) => o[s] = o, o), {})
).sort((a,b) => a.localeCompare(b)).join(", ")
Credits
NoScript XSS Trainers Hall of Fame
.mario, ableeker, Aditya K Sood, Aerik, Ahamed Nafeez, Aicke Schulz, al_9x,
Alan Baxter, Alejandro Rusell, Alex Inführ, Ashar Javed, boris, Bueller007, Chris
Lonsberry, Colling Jackson, Daethian, Dan Loomis, Daniel Holbert, dave b, Dixie,
dondado, dood_97, Edward C. Kim, File Descriptor AKA XSS Jigsaw, Gareth
Heyes, Gavin H, gazer75, Gunnar, Gunnar Scherf, Harry, HeikoAdams, hi_RAM,
Jamie Cox, Janne Maekelae, jerriy, John Danfort, John Dwyer, JonCage, Jussi
Lahtinen, Kostas, Krzysztof Kotowicz, Kuza55, LeeB, Logos, LouiseRBaldwin,
Lucas Malor, Luigi, m_c, Markus Wienand, Martin Focke, maryadavies, Masato
Kinugawa, MaZe, Mirko Tasler, MysticOrchid, Nick Fnord, niko322,
NoRelationToNed, Olaf Schweppe, Pepe Vila, Phil Purviance, Philipp Gühring,
PrinceofWeasels, RAJAH235, Roman Vock, RSnake, Salim, sharpie, Silvana,
Sirdarckcat, skl, Soroush Dalili, Stefano Di Paola, Stephen F., Stuart Young,
Sylvia Oberstein, the JoshMeister, therube, Thomas, Trupti Chaudhari, WHK,
yahoo mail user, Zoiz
Credits
● Most of these researchers use NoScript daily
and depend on its security
● Their findings get always full aknowledged
● A fix is usually released in less than 24 hours
wanna help?
CTRL+SHIFT+J
$ wget https://noscript.net/betas/noscript-2.6.9.6rc3.xpi
$ unzip noscript-2.6.9.6rc3.xpi
$ unzip chrome/noscript.jar
$ vi content/noscript/RequestWatchdog.js
$ find ./ -name "*.js" | xargs cat \
| sed '/^\s*$/d' | wc -l
22300
$ cat content/noscript/RequestWatchdog.js \
| sed '/^\s*$/d' | wc -l
2437
back to the origins
Origins
Where do we come from?
Hard question for Humans and HTTP requests
Origins
● Referrer is good, but not dependable
● Privileged does not (always) mean safe
● Sometimes you need to examine the call stack
● You always need to walk back redirections
Exceptions
● In an ideal world we shouldn't need them :(
● User can define his own (regexp-based)
● Built-in are fine grained up to skip individual
requesst parameters (GET or POST)
Escaping escapings
● (un)escape VS (d)encodeURI(component) VS
form encoding
● Base64
● XML and HTML entities
● CSS escapes
● ASCII & Unicode escapes in string literals
● Unicode escapes in JavaScript source
↖ ADDITIVE OMG!!! ↗
Escaping escapings
The kinky stuff...
● PHP overdecoding
● ASP HomoXSSuality
● ASP parameter collapse
● Flash escaping
● Ebay escaping
Ignoring the noise
● JSON, even in URL parameters
● XML!
● Common URL subpatterns
● Other expensive distractions
Looking for injections
● HTML injections
● Attribute breaking/insertion
● CSS injections
● JavaScript injections
Looking for injections
maybeJS()
Looking for injections
Regular expressions +
DOM Parser +
JavaScript interpreter =
WIN!
Sanitizer
● Blacklist of characters and constructs
● Regexp-based, replaces with spaces
● Triggered on InjectionChecker match
● Affects URLs and referrers, POST payloads get
entirely erased
● It works, but needs to go away
False positives
Please post data, not code!
● Avoid fancy cross-site POSTs (and GETs!)
● JSON & XML are OK
● JavaScript & HTML are bad
● Base64 != “obfuscation”
back to the future
Future plans
● Refactoring (less regexps, more parser)
● Remote (out-of-process) Request Watchdog
(ABE + InjectionChecker)
● Request suspension and resuming
● Safe Browsing – like error page
● False positive reporting (like ClearClick)
ThanXSS!
● giorgio@maone.net
● hackademix.net
● @ma1
● noscript.net