Tag: csrf
2010
12.07

Summary

Google Scholar was vulnerable to minor but potentially annoying CSRF vulnerabilities in two different pages. The regular search equivalents of both of these pages used CSRF tokens to mitigate these problems.

Vulnerability #1

There was no CSRF protection used when saving preferences in Google Scholar. So, browsing to the following URL used to set your language on Google Scholars to Arabic and set your search results to return papers written in Chinese: http://scholar.google.com/scholar_setprefs?hl=ar&lang=some&lr=lang_zh-CN&submit. As of right now, the URL no longer updates user preferences (although it does change the language for the current page, and any page accessed from links/forms off of that page).

Vulnerability #2

There was no CSRF check in place for setting up email alerts in Google Scholar. A simple POST to http://scholar.google.com/scholar_alerts?view_op=list_alerts&hl=en where the POST data was

1
2
3
alert_query=[SOME QUERY]&
alert_max_results=10&
create_alert_btn=Create+alert

would have resulted in an alert being created for the currently logged in user (there was a parameter, email_for_op, that was passed in during a real request: removing it seemed to cause the system to default to the currently logged in user’s email address).

More Information

The vulnerabilities mentioned here have all been confirmed patched by the Google Security Team. I owe them a ton of thanks for organizing this program and giving me a chance to improve my skills. :-)

To see more posts I’ve written about vulnerabilities reported under Google’s Vulnerability Reward Program, please click here.

2010
11.30

Summary

Google Calendar was vulnerable to a series of CSRF vulnerabilities. In two separate instances, I found that existing countermeasures (CSRF tokens) were not being validated by the application.

Walkthroughs

Example #1

In the first instance, I found it was possible to add an arbitrary event to a user’s calendar. I used Google Calendar’s “quick add” feature: it allows users to click on a space on the calendar and type in the name of an event, which adds it to the calendar. By monitoring the HTTP traffic between my browser and Google, I determined that the calendar entry was being created by a GET request that looked something like this (I’ve broken up the URL for the sake of readability):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
http://www.google.com/calendar/event?
dates=20101103T003000%2F20101103T013000
&text=asfsaf
&pprop=HowCreated%3ADRAG
&src=kmVhbF9wb29sLUBicm93bi5lZGU
&ctz=America%2FNew_York
&eid=1288669371381
&sf=true
&action=CREATE
&output=js
&lef=LHZkMjYxNDNmODNlOTBlbnZqMTQ0amh1Ym9AZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ
&lef=MW4udXNhI2hvbGlkYXlAZ3JvdXVudi5jYWxlbmRhci5nb29nbGUuY29t
&lef=bsVhbF9wb21sZUBicm92bi5lZHU
&droi=20101024T000000%2F20101212T000000
&secid=-_1FyItA6aDLfYZl6GhuK62s74o

The first thing I tried doing was removing the secid parameter (which I assumed to be a CSRF token): surprisingly, while the output of the response changed slightly, it still created a new event on the calendar. I then experimented through trial and error with removing more parameters until I got the URL down to the following:

1
2
3
4
5
http://www.google.com/calendar/event?
dates=20101103T003000%2F20101103T013000
&text=asfsaf
&sf=true
&action=CREATE

An attacker could have provided that URL to a target in any number of ways: just visiting it would have added a corresponding entry to the target’s calendar.

Example #2

The second instance involved changing the privacy settings of an existing calendar. To do so, an attacker first needed to determine the calendar’s unique identifier. I proposed the following method for finding such an identifier, assuming the target is a Gmail user (and we’re interested in their default, personal calendar):

  1. Identify the target. Lets say the target is example@gmail.com.
  2. Register a Gmail account where the first letter of the account is different from the target’s. So, here, I might register fxample@gmail.com
  3. Sign in to Google Calendar as the attacker, take a look at the printable image version of your calendar. It will have the attacker’s email address in the upper left hand corner. The URL for the image looks something like this (I’ve omitted unnecessary parameters): https://www.google.com/calendar/printable?src=[SOME STR]&psdec=true&pft=png
  4. Through trial and error, try different permutations of letters/numbers in the first few characters of the src parameter. You can see how your changes affect the decoded string by looking in the upper left of the image: it will display a new email address based on your changes (sometimes it might tell you that the src is invalid, in which case you just continue trying). There’s a small enough number of possibilities that it can be brute-forced.
  5. Eventually, you figure out what the right src value is for the target: the email on top will match the target’s email address.

From there, the rest was simple. Privacy settings are controlled by sending a POST request to https://www.google.com/calendar/editcaldetails. A CSRF token was included if the request was made via the web interface, but omitting the token did not prevent the request from functioning. The POST body consisted of just the following:

1
2
3
dtid=[VALID-SRC]
&ap=X19wdWJsaWNfcHJpbmNpcGFsX19dcHVibGljxmNhbGVuZGFyLmdvb2dsZS5jb20
&ap=20

where [VALID-SRC] was the valid src found in step 5 and the rest was a constant derived from the HTML for the corresponding form in the web interface.

More Information

The vulnerabilities mentioned here have all been confirmed patched by the Google Security Team.

To see more posts I’ve written about vulnerabilities reported under Google’s Vulnerability Reward Program, please click here.

2010
11.21

Warning

The method of preventing CSRF attacks described in this post is now considered to be insufficient. A comment on this post links to more details about an attack that circumvents it.

The Setup

About two weeks ago, I discovered a CSRF vulnerability on a well-known website (I won’t mention it by name). The vulnerability itself was fairly mundane: one of their scripts lacked tokens or any other form of CSRF protection. I sent in an email to their security team to let them know about it and went on my way.

The other day, I looked back at the website to see if the vulnerability had been fixed: it had. I also discovered that the vulnerability had been fixed using a method I had never thought about before. The website used “standard” HTTP headers, rather than a random token in the query string, to ensure that the request was from a valid source.

How does it work?

The browser makes an AJAX request. In that request, a special header is set: X-Requested-With. This header is non-standard, but it’s used by many JavaScript libraries (i.e., jQuery, Prototype).

On the server side, the server validates the request to make sure the header exists in the request. If it doesn’t, the request is rejected. If you’re using a library like jQuery, this is the only bit of code you have to implement.

Why does it work?

To add the header to a request within the context of the browser (which is what you need to do to pull off a CSRF attack properly), the attacker needs to use XMLHttpRequest. However, thanks to same-origin restrictions, XMLHttpRequest doesn’t allow you to make an AJAX request to a third party domain by default. Thus, it’s not possible for an attacker to forge a request with a spoofed X-Requested-With header.

There are, of course, some caveats:

  1. You need to use AJAX requests to take advantage of this protection: regular GETs and POSTs don’t allow for header manipulation.
  2. If your site allows some form of cross-domain AJAX requests (see https://developer.mozilla.org/en/http_access_control for more details), this won’t protect you.
  3. Like any other form of CSRF protection, it can be circumvented under certain circumstances. An insecure crossdomain.xml file, for instance, will still allow malicious Flash applets to go wild on your website.

It is, however, much better than using the Referer header. ;-)