Archive for the CSRF Category

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.

ABE
During the past weeks I’ve started a new project called ABE, sponsored by the NLnet Foundation and meant to provide CSRF countermeasures configurable on the client side, the server side or both.

As you probably know, the NoScript browser extension improves web client security by applying a Default Deny policy to JavaScript, Java, Flash and other active content and providing users with an one-click interface to easily whitelist sites they trust for active content execution. It also implements the most effective Cross-Site Scripting (XSS) filters available on the client side, covering Type-0 and Type-1 XSS attacks; ClearClick, the only specific browser countermeasure currently available against ClickJacking/UI redressing attacks, and many other security enhancements, including a limited form of protection against Cross-Site Request Forgery (CSRF) attacks: POST requests from non-whitelisted (unknown or untrusted) sites are stripped out of their payload and turned into idempotent GET requests.

Many of the threats NoScript is currently capable of handling, such as XSS, CSRF or ClickJacking, have one common evil root: lack of proper isolation at the web application level. Since the web has not been originally conceived as an application platform, it misses some key features required for ensuring application security. Actually, it cannot even define what a “web application” is, or declare its boundaries especially if they span across multiple domains, a scenario becoming more common and common in these “mashups” and “social media” days.

The idea behind the Application Boundaries Enforcer (ABE) module is hardening the web application oriented protections already provided by NoScript, by developing a firewall-like component running inside the browser. It will be specialized in defining and guarding the boundaries of each sensitive web application relevant to the user (e.g. webmail, online banking and so on), according to policies defined either by the user himself, or by the web developer/administrator, or by a trusted 3rd party.

ABE rules, whose syntax is defined in this specification (pdf), are quite simple and intuitive, especially if you ever looked at a firewall policy file:

# This one defines normal application behavior, allowing hyperlinking
# but not cross-site POST requests altering app status
# Additionally, pages can be embedded as subdocuments only by documents from
# the same domain (this prevents ClickJacking/UI redressing attacks)
Site *.somesite.com
Accept POST, SUB from SELF https://secure.somesite.com
Accept GET
Deny

# This one guards logout, which is foolish enough to accept GET and
# therefore we need to guard against trivial CSRF (e.g. via <img>)
Site www.somesite.com/logout
Accept GET POST from SELF
Deny

# This one guards the local network, like LocalRodeo
# LOCAL is a placeholder which matches all the LAN
# subnets (possibly configurable) and localhost
Site LOCAL
Accept from LOCAL
Deny

# This one strips off any authentication data
# (Auth and Cookie headers) from requests outside the
# application domains, like RequestRodeo
Site *.webapp.net
Accept ALL from *.webapp.net
Logout

Living inside the browser, the ABE component can take advantage of its privileged placement for enforcing web application boundaries, because it always knows the real origin of each HTTP request, rather than a possibly missing or forged (even for privacy reasons) HTTP Referer header, and can learn from user’s feedback.
Rules for the most popular web applications will be made downloadable and/or available via automatic updates for opt-in subscribers, and UI front-ends will be provided to edit them manually or through a transparent auto-learning process, while browsing. Additionally, web developers or administrator will be able to declare policies for their own web applications: ABE will honor them, unless they conflict with more restrictive user-defined rules.
As soon as browser support for the Origin HTTP header becomes widespread and reliable, an external version of ABE might be developed as a filtering proxy.

An initial implementation will be released during the 1st quarter of 2009 as a NoScript module.
I already collected precious feedback from security researchers like Arshan “Anti-Samy” Dabirsiaghi, Ivan Ristic of ModSecurity fame, Sirdarckcat and others.
More opinions and suggestions about rules design and features are very welcome.

A couple of months ago, Brandon Sterne of the Mozilla Security Team asked me some questions about NoScript’s internals, because he was developing a Firefox add-on which involved selective script-blocking.

Looks like he finally delivered: Site Security Policy is a proof of concept for an idea proposed by RSnake and turned into a specification by Gervase Markham, known as “Content Restrictions”.

A Site Security Policy is defined by the website administrator and communicated to the web browser as a set of special “X-SSP-…” HTTP headers either attached to the affected content or sent in response to a “discovery”

HEAD

request:

  • X-SSP-Script-Source

    specifies a deny/allow list of hosts which are allowed to run scripts.
    If this header is sent, no embedded script is allowed to run, and only included scripts whose sources match the rules are executed. This is an effective anti-XSS countermeasure, and could be extremely useful for so called “Web 2.0″ sites featuring user-generated rich content.

  • X-SSP-Request-Source

    lists the hosts which can or cannot send HTTP requests to a certain resource, and the “acceptable” HTTP verbs.
    This can help enforcing referrer-based checks against CSRF attacks which work even if user chooses to omit or spoof the

    Referer

    header for privacy reasons, and mitigating verb-tampering attacks when used to “enhance” CSRF.

  • X-SSP-Request-Target

    limits the destinations of requests originated by the current page.
    This may help mitigating data-leakage outcomes of a successful XSS attack, e.g. by preventing authentication tokens from being logged to remote hosts, but also avoiding the page to be used as a platform for CSRF attacks and blocking inclusion of unwanted 3rd party content.

  • X-SSP-Report-URI

    declares an URL where policy violation attempts should be logged by the browser.

If you want to start applying these restrictions to your web content, you’ll find a detailed yet simple reference* with examples on Brandon’s project web site.
Implementing a Site Security Policy cannot surrogate web developers’ security awareness and best practices, but it’s nonetheless a big step forward in making a website safer for its users.

Obviously enough, to be generally effective this technology still needs to be evangelized to administrators and coders, correctly deployed and supported in a consistent cross-browser fashion. But as soon as it gets built in our favourite browser and we begin to see badges like “Browsing this site is safer with Firefox”, we can hope other vendors to join making the Web a safer place.

* Update:

Site Security Policy changed its name to “Content Security Policy”, and it dropped its anti-CSRF features to focus on XSS prevention only.
Details have been relocated here.

Evil GMail by GoogHOleIf the GoogHOle wasn’t wide enough, yesterday Petko D. Petkov AKA pdp posted another “semi-disclosure” about how you can redirect someone else’s GMail incoming messages to your account.
Petko declared “I am not planning to release this vulnerability for now”, but this counts as a full disclosure in my book, since the details he gives away are far more than enough to put up a proof of concept in 10 minutes, if the reader knowns the very basics of Cross Site Request Forgery (CSRF).

  1. Victim must be logged in GMail.
  2. Victim must visit a malicious web page: most likely scenarios are clicking an external link from an incoming message or surfing porn while checking email from time to time.
  3. The malicious web site forges a POST request to GMail’s “Create Filter” wizard, possibly using an autosubmit invisible form to build a filter which forwards incoming messages to a mail recipient owned by the attacker.
  4. Since user is already authenticated, her session cookie is passed along with the forged request and the GMail filter gets silently implanted, with all the output hidden inside an IFRAME.
  5. The new GMail filter now acts as a persistent backdoor stealing incoming messages, and it will go unnoticed forever unless the victim is a power GMail user who creates or edits from time to time her own filters, which are deep buried in the “Settings” user interface: I, for instance, never saw them until yesterday!

Very clever and very dangerous.
As I said, this surely counts as a 0day public full disclosure: no matter if pdp omitted an explicit PoC. How many of us, having minimal web coding experience, wouldn’t be able to build a working exploit using the info above?

CSRF Countermeasures

As usual, now that’s been publicly disclosed, this vulnerability is being patched very quickly by the great Google development crew.
Nonetheless, many other holes of this kind are still around. That’s why CSRF is called “The Sleeping Giant”: some web coders may still need to learn how to fix or prevent them, and users surely want to know how to protect themselves.

1. Web Developers

Please use form keys!

  1. Generate a random identifier (form key) every time you display a form meant to be submitted by authenticated users only.
  2. Echo your key as an hidden field of the form and bind its value to the user session data kept on the server side.
  3. As soon the form is submitted, compare the returned key with the one stored in session data: if they don’t match, throw away the request because it is probably forged.

The above is a simple yet effective anti-CSRF technique. It will work fine unless a further Cross Site Scripting (XSS) vulnerability is present too, allowing attacker to read your form key on the fly and forge a seemingly valid requests.

2. Web Users

This GMail incident proves how even the best trained web developer in the world can fail at implementing CSRF countermeasures.
Most of the existing literature about XSS and CSRF will tell you that poor users can do nothing to protect themselves from these attacks, but this is blatantly false.
A quite radical, not very usable but effective approach would be using different browsers (or different profiles, if you use Mozilla derivatives) for each “sensitive” web site you access, and force yourself not to follow any external link nor browse any other site while logged in.

Anyway, if you prefer not to make your life miserable by spawning multiple browsers and scanning every single link with a magnifying lens, your answer is, once again, Firefox + NoScript (sorry to sound repetitive, but that’s it).

First of all, automating a POST request is trivial if JavaScript is enabled on the attacker site —

form.submit()

— but just impossible if malicious scripts are blocked by NoScript.
The obvious objection, raised for instance by both pdp and Adrian Pastor at GNUCITIZEN, sounds like:

The attacker could simply build an invisible POST form and disguise its “submit” button as a regular link or an image, then social-engineer his victim into clicking it and so have the exploit launched no matter if JavaScript is disabled.

True, but NoScript effectively defeats this attack as well!

A common misconception about NoScript is that it just blocks JavaScript on untrusted sites.
It certainly does, but NoScript actually enhances browser security in several other ways.
A very incomplete list:

  1. It blocks Java, Flash, Silverlight and other plugins on untrusted sites, and optionally also on trusted pages, while letting you activate the plugin content on demand, with a click.
  2. It prevents malformed URIs to exploit buggy URI handlers, i.e. the foundation for many cross-application exploits discovered by Billy Rios, Nate McFeters and Thor Larholm.
  3. It implements the most advanced and effective anti-XSS protection available on the client side.

NoScript’s anti-XSS protection deploys various specific countermeasures, e.g. HTML/JavaScript injection detection, URL sanitization on suspicious cross-site requests, UTF-7 encoding neutralization and many others.
One of them also provides an effective defense from CSRFs of the kind affecting GMail: in facts, NoScript intercepts POST requests sent from untrusted origins to trusted sites and strips out their payloads.
This means that, even if the attacker exploits a scriptless vector to launch his POST CSRF through social engineering, NoScript users are still safe as long as the malicious site is not explicitly whitelisted.

When he learned this, pdp commented:

Giorgio, sounds good, but doesn’t that break things?
I mean, CSRF is one of the most fundamental Web characteristic.
Disabling it might be OK for people like us, but for the general population, that is a no go!

Petko, my friend,

  1. The very foundation of the Web is CSR (Cross Site Requests, AKA Hyperlinking), not CSRF (Cross Site Request Forgery) which is an unwanted side effect of bad coding practices.
  2. RFC 2616 defining HTTP (hence, in a certain sense, the Web itself), clearly states that while GET requests (the ones we generate by following hyperlinks or submitting a search form) are idempotent, i.e. should not modify the receiving system, POST is reserved to requests which cause a permanent change. NoScript just prevents untrusted sites from modifying data held by trusted sites, and this looks Pure Good™: why could you want the contrary?
  3. Even if you actually wanted the contrary, you can either use the “Unsafe reload” command, available whenever a request is filtered by NoScript, or permanently configure some sites of your choice as unfiltered recipients of unsafe requests by listing them in NoScript Options/Advanced/XSS/Exceptions

The NoScript feature we’re talking about has been in place for more than six month now.
I guess it’s transparent enough if security researchers like you, Adrian or .mario — people “like us”, much more attentive to what happens inside their browsers than “the general population” — did not even notice it… ;)

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