Archive for January, 2009

Sooner or later you, dear NoScript user, may face this puzzle: you already allowed every single script source looking "legitimate" on a certain page, but the damn thing stubbornly refuses to work as it should. Then, in a moment of enlightenment, you dig inside your Untrusted menu, and there you find google-analytics.com. You put it there long ago because you don't like to be tracked, but now you cross your fingers and temporarily allow it... et voilà, the page starts behaving!

Now, you may ask why the hell a web site requires Google Analytics scripts to be enabled for providing its basic features, and you might be right: no reason for that. On the other hand, a growing number of web sites leverage Google Analytics for more than just tracking page views and navigation: they also try to collect finer grained usage data about some specific features of theirs. Therefore they call functions or reference objects from http://www.google-analytics.com/ga.js from their own "1st party" specific scripts, e.g. when you click a certain button: if google-analytics.com is blocked by NoScript (or by AdBlock Plus, or by your hosts file, for the matter), the 1st party code referencing it will obviously fail and the button will stay dead. You can be hinted about Google Analytics being the culprit by opening Tools|Error Console and watching for errors like "urchinTracker is not defined" or "_gat is not defined”.

So far, all you could do about that was allowing google-analytics.com. But latest NoScript (1.8.9.7 or above) implements a new feature, called Surrogate Scripts, which works around this problem out of the box and is customizable enough to cope with similar 3rd party script issues in the future. How does it work? Very simple: whenever an external script is blocked, NoScript checks if its URL matches a certain pattern, and if it does an alternate user-provided surrogate script gets executed instead, in the context of the loading page. There you can define surrogates for any required object or function.

There's no UI for this feature (yet?), but its intended audience is likely geeky enough not no need one.
You can specify as many URL/surrogate mappings as you want, by creating a couple of about:config preference entries under the noscript.surrogate root.
The built-in Google Analytics mapping can be regarded as a reference:

  • noscript.surrogate.ga.sources: *.google-analytics.com
  • noscript.surrogate.ga.replacement: var _0=function(){};with(window)urchinTracker=_0,_gat={_getTracker:function(){return {__noSuchMethod__:_0}}}
    var _0=function(){};with(window)urchinTracker=_0,pageTracker={_setDomainName:_0,_trackPageview:_0,_initData:_0},_gat={_getTracker:function(){return window.pageTracker}}*

If you want to exempt some pages from this replacement (e.g. because they already provide a graceful fallback for missing external scripts), you can add an URL pattern to the noscript.surrogate.ga.exceptions preference, e.g. *.mozilla.org *.mozilla.com. Script Surrogates can be disabled globally by setting noscript.surrogate.enabled to false.

Happy hacking :)

*Update

Jesse Andrew told me about some Google Analytics API not covered by the original surrogate, so rather than trying to find out every possible tracker method, present and future, I decided to catch them all by exploiting a nifty Mozilla JavaScript feature, i.e. __noSuchMethod__. Please get 1.8.9.8 (latest development build) if you want to this more reliable approach right now.

Update 2

Since I've been asked by concerned non-geeks (especially those who can't read JavaScript code) what exactly the Google Analytics surrogate does, here's a plain English description: the Google Analytics surrogate script does NOTHING. It’s a dummy “catch all” replacement for the most common Google Analytics functions: it makes the calling pages happy, helping not to break sites, but doesn’t send nor receive anything to/from Google.

Update 3

NoScript now supports a second kind of script surrogates, called "Page-level surrogates": if the sources patterns start with the "@" character, the replacement scripts are executed before the matched page starts to be parsed and before any other script can run. This allows preemptive patching of the loading page, similarly to GreaseMonkey but in a more pervasive way, since GreaseMonkey's scripts can run only when the DOM is already parsed (i.e. after page scripts already run).

Davide had no better stuff to do, so here I am (hating him), abiding to these rules:

  1. Link to your original tagger(s) and list these rules in your post.
  2. Share seven facts about yourself in the post.
  3. Tag seven people at the end of your post by leaving their names and the links to their blogs.
  4. Let them know they’ve been tagged.

7 Facts

  1. I don't consider myself a bearded guy: I shave my face whenever I find 10 spare minutes to do it. That's once per month on average, therefore for most people I meet I am a bearded guy nonetheless.
  2. I received a fifteen years long salesian catholic education (7 years with nuns, while I was 4-10, and 8 years with priests, 11-18). I suspect this had a big part both in the depth/breadth of my scriptural/doctrinal knowledge, and in my ultimate (consequential?) militant atheism. Which prompts an interesting paradoxical question: what should I better do to raise my soon to be released child as a free thinker?
  3. My first computer was a Commodore 64... wait, you might know this one... OK, but you may not know that when I was 12 I wrote a trilogy of C64 school-themed video-games depicting my priest-teachers as flying horned devils. I sold them among my schoolmates with some good financial success (that was a so called "elite" school).
  4. My first web page, established on Geocities back in the past century and entirely built with Amiga technologies, was the Marxism-Leninism-Prodism-Gargarism home page. I lost my credentials, and even if I did try several times to make Yahoo pull it down I'm afraid it will persist as an indelible stain on my past. It was somehow prophetic about the dissolution of any serious left-wing in Italy, though...
  5. I met my wife, a teacher of Greek and Latin and a published author of school textbooks, when we both were 15, and we've been good friends albeit living in two different towns for more than ten years, meeting once every two years or so. Then I had to teach a short course in her town, staying there for a couple of weeks, and when I was about to leave I suddenly asked her to marry me. She just exploded in a loud laughter. But after less than of one month, she relocated to live with me. I punished her offensive initial reaction by making us "live as public sinners" for another ten years, until I decided it was time to perpetuate our genes :)
  6. Both my thumbs can bend backwards by 90 degrees (much like in Andrès Segovia's right hand).
  7. Since I was 18 I wear an hammer and sickle-shaped piercing on my left earlobe.

7 people I'd like to inflict the same agony

No matter our views about the Israeli bloody war* terrorism against the Palestinian people, Al Jazeera can teach us some lessons about openness and information democracy: its broadcast-quality video footage shot in Gaza is released under the least restrictive Attribution license.
Quoting the CC' blog:

Each professionally recorded video has a detailed information page and is hosted on blip.tv allowing for easy downloads of the original files and integration into Miro. The value of this footage is best described by an International Herald Tribune/New York Times article describing the release:

In a conflict where the Western news media have been largely prevented from reporting from Gaza because of restrictions imposed by the Israeli military, Al Jazeera has had a distinct advantage. It was already there.

More importantly, the permissive CC-BY license means that the footage can be used by anyone including, rival broadcasters, documentary makers, and bloggers, so long as Al Jazeera is credited.

There’s more information over at Al Jazeera’s CC repository, and in our press release. You can also add the Al Jazeera repository to your Miro feeds by clicking here

So, rather than labeling its unique original footage as "exclusive", the Arabian network is giving it away for anyone (competitors included) to watch, analyze, share and reuse, leveraging an open source (GPL) open media platform and hosting it on an open source (GPL) CMS.
What do you think?

Looks like my follow up to Gareth Heyes' Twitter Hack produced two effects:

  1. Twitter guys closed their hole by requiring an additional basic HTTP authentication step to retrieve the friends timeline JSON feed. Well done, albeit still lacking as an anti-CSRF countermeasure, because if user already performed basic authentication for any reason during this session, the hack still works flawlessly (not sure about how likely this is, though).
  2. Some readers complained about me slightly criticizing Adblock Plus' new 3rd party blocking, by calling it "rather inconvenient" (especially if compared with the new NoScript 1.8.8.95's anti-hijacking protection which doesn't require any script blocking), although I was actually praising the famous ad blocker as a countermeasure against this attack.
    Yesterday evening, when I wrote that post, I was overly tired from a very stressful week, so I fell in the trap of suggesting to use Adblock Plus for a security purpose. After some sleep, a bit more in my mind, I recalled why I always recommend Adblock Plus as a wonderful annoyance blocker, but not to be relied upon for security: there are too many easy ways to circumvent it.
    More in general, Adblock Plus and FlashBlock, despite a popular superstition, can’t be considered security tools because they’re not conceived nor developed with the necessary defensive and proactive paranoid mindset.

I updated my PoC to reflect both these events.
Now it "hijacks" Twitter's public listings feed which, as the adjective "public" suggests, has no reason to be protected.
And this time Adblock Plus' 3rd party blocking won't help :)

Are you logged in Twitter?

Some days ago my friend Gareth Heyes exposed an authorization bug in Twitter's JSON interface, by writing a short post titled I Know What Your Friends Did Last Summer. Do not click on his PoC with JavaScript enabled, unless you want to find yourself bombed by a lot of alert boxes showing some interesting Twitter data about you and your friends.

For your convenience, I've reproduced a less annoying PoC here:

Are you logged in Twitter?

Notice/update: after some hours this article was out, Twitter secured its "friends timeline" feed. Therefore I updated this PoC to consume the "public" feed, still demonstrating the hijacking technique, albeit on a non-sensitive data set.


Twitter's JSON feed is spied upon using __defineSetter__, a useful JavaScript extension introduced by Mozilla and now implemented in all the modern browsers (i.e. all the popular ones except IE). After redefining a property setter on Object.prototype, we can read the values being set when the feed is loaded through a <SCRIPT> element:

Object.prototype.__defineSetter__("user",
  function(value) { // do something with user's value }
);
<script src="https://twitter.com/statuses/friends_timeline/"></script>

The main problem here is, obviously, Twitter leaving this feed unsecured against cross-site requests, under the wrong assumption that it could be read only through XMLHttpRequest (which actually does not work cross-site). We can expect errors like this to be quite widespread, since so-called "AJAX security" is still in its infancy: consider that Twitter guys are not exactly newbies...

This JSON-hijacking technique won't work if any of the following conditions applies:

  • The feed provider (Twitter) secures its JSON to ensure 3rd party sites can't access it (i.e. implementing any anti-CSRF countermeasure).
  • The JSON payload is not enclosed in square brackets. If the JSON starts directly with curly braces, it gets intepreted as a code block, rather than an object initializer, and nothing happens.
  • You're using an antiquated browser (like IE).
  • JavaScript execution is disabled on the attacker's site (e.g. by using NoScript in its default configuration).
  • You're preventing 3rd party scripts from loading (e.g. by using Adblock Plus with its rather inconvenient 3rd party script blocking feature enabled). Forget it, too much easy to work-around :(
  • You're using NoScript 1.8.8.95 or above, even if you're allowing scripts everywhere!

Yes, that's right: in the best NoScript tradition, while there's some ongoing work to prevent this kind of leakage from happening in next major version of Firefox, NoScript already provides a specific protection feature. Even better, this works even in Allow Scripts Globally mode, just like anti-XSS filters and the ClearClick anti-clickjacking technology, so you've got no excuse to stay unsafe.

P.S.:
another thing you can do for your Twitter security, especially if you use public wifi, is adding twitter.com to your HTTPS behavior forced list and enabling automatic secure cookies management, to defeat cookie hijacking attacks.

Update

Twitter fixed this issue by requiring HTTP authentication in order to retrieve the https://twitter.com/statuses/friends_timeline.json feed.
I'll post a new innocuous didactic PoC fetching the public feed and circumventing Adblock Plus as soon as I'm done with breakfast.

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