Archive for the XSS Category

When I started implementing NoScript’s Anti-XSS filters, about one year ago, they were admittedly over-zealous, detecting too many false positives.

But a lot of work has been done since then, and today I’m very proud of the Injection Checker component, which is capable of spotting reflective XSS attacks, no matter how exotic or obfuscated they are, with extreme accuracy and the lowest false positive rate.
A sla.ckers thread entirely dedicated to hacking NoScript has not gone much far (special thanks to Gareth Heyes, by the way, for the few issues he actually found). On the other hand, the engine became smart enough to recognize syntactically valid JSON as innocuous and let it pass through, while any Web IDS out there would just scream fire.

Hence the very few (3 in 3 months) false positive reports I received recently brought me to investigate the sites, rather than NoScript’s behavior, and the finding have been quite interesting…

CNN: Vulnerable by Design

A NoScript user complains about popups on cnn.com triggering XSS warnings, and wants to know how to disable them.
I answer as I always do, asking him to open the Error Console and send me the lines starting with “[NoScript XSS]”, which detail the URLs where the problems happen and the filtering actions taken by NoScript. In his case,

[NoScript XSS] Sanitized suspicious request.
Original URL [http://www.cnn.com/cnn_adspaces/dart_ads/2007/12/21/orbitz.html
?clk=http://ads.cnn.com/event.ng/Type%3dclick%26FlightID%3d103458
%26AdID%3d160329%26TargetID%3d1095%26Values%3d1588%26Redirect%3d
&imp=%3Cimg%20src%3D%22http%3A//ads.cnn.com%3A80/event.ng/Type%3Dcount%26ClientType
%3D2%26AdID%3D160329%26FlightID%3D103458%26TargetID%3D1095%26SiteID%3D1588
%26EntityDefResetFlag%3D0%26Segments%3D730%2C2592%2C2743%2C3030%2C3285%2C6298%2C8463
%2C8796%2C9496%2C9779%2C9781%2C9853%2C10381%2C13153%2C13760%2C14173%2C14248
%2C14401%2C14402%2C14734%2C14735%2C14736%2C14757%2C14758%2C14760%2C14863%2C14864
%2C14879%2C14887%2C14960%2C14961%2C15022%2C15031%2C15032%2C15033%26Targets%3D1095
%2C2742%2C1515%2C24516%2C26849%2C28114%26Values%3D30%2C46%2C50%2C60%2C72
%2C84%2C90%2C100%2C110%2C150%2C682%2C917%2C1067%2C1285%2C1557%2C1588
%2C1601%2C1604%2C1678%2C1735%2C1815%2C2677%2C4405%2C4413%2C4418%2C4438
%2C37353%2C47181%2C47458%2C49282%2C49553%2C49657%2C49935%2C52263%2C52508%2C52897
%2C54681%2C54738%2C54765%2C55058%2C55059%2C55695%26RawValues%3D
%26random%3Dkxauis%2CbdWjwiovNwhlK%22%20width%3D1%20height%3D1%20border%3D0%3E
&rand=kxauis,bdWjwiovNwhlK]

Careful readers already noticed the weird imp parameter, which can be unescaped into

<img src="http://ads.cnn.com:80/event.ng/Type=count&ClientType=2&
[...]random=kxauis,bdWjwiovNwhlK" width=1 height=1 border=0>

Ehy, they’re passing HTML fragments around in query parameters… no wonder NoScript cries. But they’re the CNN, they surely know what they’re doing and won’t allow arbitrary injections, will they? Let’s look at the code, perhaps we’ll learn some new best practice:

<script language="javascript"><!--

//SCRIPT TO PARSE PASSED VALUES

var clk;
var imp;
var rand;
var urlQuery = ( location.search ) ? location.search : '';
var queryString = (( urlQuery != '' ) && ( location.search.charAt( 0 ) == '?' )) ? urlQuery.substring( 1 ) : urlQuery;
var pairs = queryString.split("&");

Thanks for this wonderful tip on how to write
var pairs = location.search.replace(/^\?/, '').split("&");
in a maintenable and readable form! Let’s dig for other treasures…

for (i=0; i < pairs.length; i++) {

var pos = pairs[i].indexOf('=');
if (pos == -1) continue;
var argname = pairs[i].substring(0, pos);
var value = pairs[i].substring(pos+1);

Right, one split() per script is enough: let’s revert to good old string manipulation, especially in loops!

if(argname == "clk") {
clk = value;
clk = unescape(clk);
}
if (argname == "imp") {
imp = value;
}
if(argname == "rand") {
rand = value;
}
}

Mmm, they’re clearly parsing query parameters into variables. Wonder what they want to do with them?

//SCRIPT TO WRITE CLIENT CODE WITH CLICKTHRU

document.write("<IFRAME SRC='http://ad.doubleclick.net/adi/N2870.cnn/B2094897;sz=720x300;click="+
clk+";ord="+rand+
"?' WIDTH=720 HEIGHT=300 MARGINWIDTH=0 MARGINHEIGHT=0 HSPACE=0 VSPACE=0 FRAMEBORDER=0 SCROLLING=no BORDERCOLOR='#000000'>");
document.write("</IFRAME><br><br>");

Ahem, were clk and rand entity-escaped? Looks like they already put a couple of XSS insertion points here…
But the best part has to come yet:

//SCRIPT TO WRITE $SMARTCOUNT$

imp = unescape(imp);
document.write(imp);
-->
<script language="javascript">

Ouch, $SMARTCOUNT$ is the <img> code above (likely a tracking image), ant it gets injected verbatim inside the page!

So, to recap, CNN advertising system intentionally uses XSS to insert Web Bugs, and calls this clever solution Smart Count!

CeBIT: Even More Vulnerable by Design

For those who don’t know it, “CeBIT is the world’s largest trade fair showcasing digital IT and telecommunications solutions for home and work environments“.

Date: 17 Feb 2008 19:52:43 +0100
Subject: XSS false positive on CEBIT.DE

Hi,

I experienced problems using noscript on http://www.cebit.de/ when
registering tickets online. Just try to login as a test. Even when
allowing JS in Noscript it still complains about loading insecure
content. Will be an issue for quite a lot german users in the next month.

Thanks for your great work!

Greetings from Germany,
Jan

Date: 17 Feb 2008 20:12:01 +0100
Subject: Re: XSS false positive on CEBIT.DE [NoScript]

Hi Jan,

it’s not a false positive.
The registration system is quite brain damaged, using XSS to communicate back and forth.
Whoever implemented it, has no idea of what web security is.

The “false positive” URL is

http://www.cebit.de/suche/registrationController.html?backval=
%3Chtml%3E%0A+%3Chead%3E%0A++%3Cscript+language%3D%22javascript%22%3E
%0A++++try+%7B%0A+++++if+%28parent.callback_login%29+%7B
%0A++++++parent.callback_login%28%27-1%27%29%3B%0A+++++%7D
%0A++++%7D+catch+%28e%29+%7B%0A++++++alert%28e%29%3B
%0A++++%7D%0A++%3C%2Fscript%3E%0A+%3C%2Fhead%3E
%0A+%3Cbody%3E%0A+%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A

or, unescaped:

http://www.cebit.de/suche/registrationController.html?backval=
<html><head><script language="javascript">
try { if (parent.callback_login) { parent.callback_login('-1'); } }
catch (e) { alert(e); } </script></head>
<body></body></html>

As you can see it’s a whole web page, including script, posted as a “backval” variable to be injected, smelling a gaping vulnerability.

Just try this “classic” PoC:

http://www.cebit.de/suche/registrationController.html?backval=
<script>alert(document.cookie)</script>

So, NoScript is absolutely right and they need to fix their site as soon as possible.

Cheers

Giorgio

Date: 17 Feb 2008 20:32:35 +0100
Subject: Re: XSS false positive on CEBIT.DE [NoScript]

Hi,

ok you are right. Its braindead. Sorry, I did not really check it! Looks quite exploitable. I will inform cebit and later the press (heise.de).

Greetings,
Jan

Opening http://www.cebit.de/ with cebit.de in your NoScript whitelist still triggers (rightful) XSS notifications because of a full web page embedded in the query string.
The only difference now is that an extra parameter called code has been added: from a cursory inspection, it seems they’re checking some hash of the HTML (probably stored in session) before inserting. A poor patch for a sublimely poor design…

TypePad: OK, Shit Just Happens

Date: 15/04/2008 22.17
Subject: NoScript Bug

You guys make NoScript, right?
[…]
You might want to add ^http://www.typepad.com/t/comments$ to the
default Anti-XSS Protection exceptions. It’s ridiculously common and
it always triggers an “unsafe reload” but you can’t post to TypePad
blogs without allowing it and I don’t think it’s actually harmful.

- Matt

From a philosophical point of view, TypePad stands way better than CNN and CeBIT: at least they seem to know XSS is dangerous and don’t “use” it by design.
However that very URL is vulnerable at first shot, and it may even be a persistent injection (I didn’t verify, because the test blog was moderated).
Considering that it’s “ridiculously common“, I do think it’s “actually harmful“.

Conclusion

Given the current sensitivity/accuracy balance of NoScript’s Injection Checker, I’m unlikely to add any new default XSS Protection exception: I’m actually more inclined to remove the three original ones.
But if you’re the owner of a ridiculously popular “web property” and you feel you deserve a XSS filtering exemption, feel free to contact InformAction’s sales department and request a quotation for a full “NoScript Certified” Package (vulnerability scanning + web security assessment + code audit + weekly test annual subscription). It’s gonna be ridiculously expensive and no, Scanless PCI definitely cannot surrogate ;)

Just read on Wired: Finnish Harry Sintonen reported a cross-site scripting vulnerability on CIA’s web site.
The article has been published yesterday, the bug is not fixed yet… I can’t believe secret service über-geeks do not read their logs: it must be a sneaky honey pot to convict hax0rs, dangerous Wired readers and possibly open source terrorists!

Actually, I could see quite a number of gaping XSS holes just on that search page which, as you can notice, is served through HTTPS, making it an excellent phishing hook.
I wonder if there’s also a reserved area (e.g. a CMS) somewhere on the same domain (cookies, yum!)

Even if it’s classified information, Wired itself revealed that attacks of this kind fail if you use Firefox + NoScript.
Am I already an Al-Qaeda target?

Today on PC Magazine’s Security Watch:

Two vulnerabilities in Norton Internet Security 2008 have been patched by the vendor. The vulnerabilities were reported by VeriSign’s iDefense (here and here).

The vulnerabilities are in an ActiveX control installed by NIS 2008 which is marked safe for scripting. The vulnerability could allow for remote code execution by an unauthenticated user; on the other hand. The bug is, nevertheless, difficult to exploit, and no public exploit exists.

According to iDefense, it would need to be executed in the context of the symantec.com domain. This could be accomplished through cross-site scripting on the symantec.com site—which would require incompetence on the part of that site’s administrators and authors—or through DNS cache poisoning attacks against the user. Both are probably hard to do.

Yes, of course… (Notice: Symantec XSS vulnerability fixed later, on April the 10th)

BTW, isn’t that a Google Search Appliance?

Update 1

Despite Symantec’s search functionality being provided by Google Search Appliance, the XSS vulnerability above seems a genuine home-grown customization.

Update 2

This is quite hilarious (from Brian Krebs’s Security Fix column on Washington Post):

Despite the fact that most of these Web site security flaws are posted to a publicly accessible archive site, only 473 of the cases discovered in the last half of 2007 were fixed by the end of last year, Symantec said.

Update 3 (10 Apr)

Symantec guys finally fixed their XSS vulnerability.

The future of malware doesn’t belong to our hard disks.
While we’re still trying to harden our PCs against malicious executables by using unprivileged accounts, wrapping our browsers inside sandboxes and trusting antivirus programs, our digital assets are quickly moving to another place: how much of our identity and money is already on the Web? Even better, how much of our identity and money is not available somewhere on the Web yet?

Since most malware is after our identity, our money or both, why shouldn’t it follow the same path?
And if today’s malware mostly runs on Windows because it’s the commonest executable platform, tomorrow’s will likely run on the Web, for the very same reason. Because, like it or not, Web is already a huge executable platform, and we should start thinking at it this way, from a security perspective.

I know my words may sound too much speculative, even plain FUD, but real scams and very scary proof of concepts are already here, mocking the “old school” belief that only local execution and privilege escalation are severe threats:

  • Real scamThe ultimate bank phishing using XSS.
    The credential harvesting form has been embedded inside the real bank page, served through a “secure” HTTPS connection with a valid SSL certificate, exploiting a reflected XSS vulnerability. Absolutely nothing new, and a relatively poorly performed trick too: the attackers could have as easily choose to host the whole payload inside their XSS vector itself, making their fraud even stealthier without the remote inclusion of an external resource from a different domain. But since they didn’t, surely they estimated their way is good enough to work — and it is, much more than any other phishing attempt you’ve seen so far, because this is the real bank site!!!
  • Scary Proof of ConceptMalicious web page hijacking your router.
    You may think you’ve already heard this one: “Just change the default password, it’s basic common sense” you say.
    But this time it’s different: GNUCITIZEN guys show us how to compromise your router’s DNS settings from the web with no need to log in, by exploiting its “cool” UPnP features through XmlHttpRequest (if a XSS vulnerability is available, as it happens in many devices) or Flash (if no XSS is found). And once an attacker owns your router’s DNS, he controls all your LAN, not just your own traffic…

Does anybody still believe browsing the Web with Flash and JavaScript promiscuously enabled and no XSS protection is a good idea?

Rich Cannings recently documented Flash-based XSS, clarifying with some examples the quite fuzzy coverage this issue received so far.
Its “The Fix / Users” section says:

Update to the latest version of Flash Player plugin. This will protect users from attacks using the “asfunction” protocol handler

Unfortunately, the majority of the examples listed right there do not use the “asfunction” protocol handler at all!

More realistically, Jeremiah Grossman writes:

- Users update their Flash player – Based on the nature of the issue, I’m not certain of how much benefit to this there is, but might as well patch anyway if there is one available.

- Disable or block Flash content – I think most people reading this probably already do some form of Flash blocking, but for everyone else, there are simply not going to.

Now, the “some form of Flash blocking” Jeremiah’s talking about is most likely NoScript, which:

  1. Blocks Flash (and other plugins) by default when the content comes from an untrusted web site
  2. Blocks Flash (and other plugins) by default when content from a trusted website is embedded in an untrusted page - this prevents embedded Flash XSS
  3. Checks cross sites requests for script injection and sanitizes them as needed - this prevents reflected XSS, included the Flash variants

The best thing, making this approach much more viable than “disabling Flash content” tout-court, is that you can allow individual blocked content pieces with a click, having a chance to examine their types and full addresses before running them: this is what may save you from being owned in a Flash ;)

Bad Behavior has blocked 1649 access attempts in the last 7 days.