about    blog     feed    archive

Adobe Flash: Bypassing the local sandbox to exfiltrate data, obtain Windows user credentials (CVE-2016-4271)

Update 23-11-2017: Here is the slide deck for my OWASP talk on Adobe Flash vulnerabilities CVE-2017-3085 and CVE-2016-4271. The live recording is up too!

September 2016 marked the arrival of Flash Player 23. This time, it was more than just a security patch: Adobe disables the local-with-filesystem sandbox from this release forward.

Having been part of Flash since ActionScript 3, introduced some ten years ago, the local sandbox’s demise is pretty significant. For developers, this means they will have to make the necessary adaptions. Ironically, with some of the Flash APIs now being deprecated, local file system interaction likely will require resorting to HTML5 techniques.

Historically, the local sandbox has been a popular target for devising various bypass vulnerabilities. Data exfiltration is one of them. This has resulted in an ongoing arms race, with Adobe blacklisting keywords and pseudo URIs, and white hats (plus others) finding ways around those blacklists.

With the local sandbox seemingly being a popular target, early last year I decided to join the race and have a look as well. This turned up a subtle but interesting flaw. In short, a combination of two URI schemes enable SMB access, sufficient to exfiltrate local data, and expose Windows user credentials to a remote server.

Having reported this design flaw to Adobe, it was acknowledged in APSB16-29 and assigned CVE-2016-4271. It turns out my report contributed to Adobe’s decision to drop the Flash local sandbox, so here’s a write up of how the flaw works.

By definition, not so local

When opening a local SWF file, it is intended to run in the default Flash sandbox dubbed local-with-filesystem. From Adobe, we have:

local file: A local SWF file describes any file referenced by using the “file” protocol or a UNC path, which does not include an IP address or a qualifying domain. For example, “\test\test.swf” and “file:\test.swf” are considered local files, while “\test.com\test.swf” and “\192.168.0.1\test.swf” are not considered local files.

local-with-filesystem: The default sandbox for local files. SWF files in this sandbox may not contact the Internet (or any servers) in any way—they may not access network endpoints with addresses such as HTTP URLs.

Both definitions are somewhat peculiar. We will illustrate this by discussing the mentioned schemes that locate a resource: UNC and the File URI.

Windows supports the UNC scheme to locate shared files and devices. A UNC string has a myriad of possibilities, with paths being expressed using an IP address, FQDN or NetBIOS host name. Hence, UNC paths are quite complex, and most importantly, in principle anything but local. Therefore, to meet the local file definition, Flash’s URLLoader disallows paths including an IP address, FQDN, or NetBIOS name - but with the latter category still permitting the local host’s name. Examples of valid UNC syntax include

\\10.0.0.1\share\remote_resource.txt
\\[local NetBIOS host]\c$\local_resource.txt

where only the second is accepted by Flash.

What about the other option - the File URI? This scheme expresses another variety of locations, albeit restricted to the local file system. There is one caveat, though: one path can be expressed in more than one way. From Wikipedia,

file://localhost/c|/WINDOWS/clock.avi
file:///c|/WINDOWS/clock.avi
file://localhost/c:/WINDOWS/clock.avi

all refer to the same resource. We will see later how this characteristic comes into play.

What’s in a scheme: exfiltrating local data

To summarize, we have the UNC and File URI schemes, with Flash restricting the former, and the latter taking only local paths. Now, what if we could combine them in one string? Taking the File URI as the top level, the Win32 Shell API conveniently lets us proceed using UNC notation by prepending the UNC path with /, and replacing any back slashes with their forward counterpart. We have:

(UNC syntax)               \\10.0.0.1\share\remote_resource.txt
(File URI + modified UNC)  file://///10.0.0.1/share/remote_resource.txt

where both refer to the same resource.

URLLoader presumably calls the Win32 API at some point, and so this raises the obvious question of interest: does Flash still restrict UNC when inside a File URI string? Consider these examples:

(1) file://///evilserver.com/
(2) file://///23.100.122.2/
(3) file://///192.168.1.1/

(1) and (2) throw a SecurityError as expected:

Trying evilserver.com Figure 1. Connecting to evilserver.com

Interestingly though, (3) throws a different error: Trying a C IP address

Figure 2. Connecting to an IP address

Code #2032 is Flash terminology for Stream Error. Let’s see what actually happens: Wireshark trace 1

Figure 3. Wireshark trace

Success! We have established an SMB connection from the victim’s machine to our remote server.

With local-with-filesystem providing local file system access, we still need a means to upload the data from the victim’s machine. No Flash API will let us write to SMB resources, so we have to come up with something else. The basic approach is to append file content to the SMB path request. From there, the steps to take include:

  • Format file content to meet SMB path request limits:
    • Split content into <260 bytes chunks (path MAX_LEN)
    • URL encode to avoid forbidden characters (e.g. /, \, #, @)
  • Append chunks to SMB resource requests
  • Make the consecutive requests
  • Capture requests on remote (attacker-controlled) side
  • URL decode, reconstruct complete file on remote side

Having done all that, our malicious Flash application outputs:

CVE-2016-4271-localfileexfil-msedge.png Figure 4. Client-side: exfiltrating local files on Edge

Meanwhile, we create a Python script doubling as SMB server and requests logger. On the attacker-controlled side, we have:

CVE-2016-4271-localfileexfil-terminal.png Figure 5. Server-side: capturing SMB requests

This shows we have succesfully exfiltrated a local file - to be precise, the Windows hosts file - from the victim’s machine.

SMB at play: leaking Windows user credentials

Server Message Block, commonly abbreviated as SMB, is the protocol of choice for sharing files over Windows networks.

SMB’s primary authentication scheme uses NTLM hashing to send over user passwords. This hash should be handled with caution: an 8-character password permutation can be bruteforced in under 6 hours, or if you are unlucky, less with a decent rainbow table.

Unfortunately, keeping your hash private may not be that trivial. A victim’s machine can be made to transmit user credentials along with any of its SMB requests. One option is to have the SMB server deny access without authentication, effectively signalling Windows to try logging on with current user credentials. In essence, this translates to sending the username in plain text as well as the NTLM password hash. Hence, all it takes for an attacker to obtain user credentials is triggering Windows to connect to their malicious SMB server, let that SMB server deny access without authentication, after which the Windows machine will send the password hash.

SMBtrap, a Python script using impacket’s SMB support, leverages this characteristic to do just that. It hosts an SMB server, performs protocol negotiation and session setup, and finally terminates at the point where it receives user credentials:

smbtrap Figure 5. SMBtrap output

In the above example, I have provided SMBtrap a precomputed NTLMv2 hash for the password ‘123321ab’. However, SMBtrap can be adapted to incorporate a real dictionary or invoke a tool like Hashcat.

One may consider this flaw particularly worrying. A typical Windows account, being part of the Administrators group, has the ability to self-elevate. While this would still require an RCE, privilege escalation becomes significantly easier. Impersonating the user and then using the returned token handle will usually suffice to run arbitrary processes with elevated privileges.

A word about affected versions

The flaw as described descends from Flash Player’s security design. I have verified all supported browsers and Microsoft Office products are vulnerable. Hence, this raises the question: how long has the flaw been part of Flash?

To answer this question, we return to ActionScript 3. Flash Player 9, released in June 2006, introduced this scripting language version and its corresponding sandbox policies. Attempting to run the SWF in Flash Player 9 gives:

flashplayer9 Figure 6. PoC on Flash Player 9

That looks surprisingly similar.

Conclusion

The flaw at hand is subtle but unforgiving: the File URI, being taken as local, effectively whitewashes the remote UNC path and therefore slips through Adobe’s blacklist.

Arguably, a blacklist approach is likely to fail at some point. That is, without even having considered other allowed schemes, like pseudo and custom URIs. On the other hand, with Windows enabling to combine multiple URI schemes in one, constructing a proper whitelist would seem a difficult task.

Fortunately, the local sandbox’s demise renders this question moot. For websites still requiring Adobe’s runtime, browsing the web just got a little safer as the process of deprecating Flash continues.

Overview

Affected host environments
Firefox
Chrome
Internet Explorer 6 to 11
Edge
Microsoft Office 2010, 2013 and 2016
Affected platforms
Flash Player 9.0.16.0 to 22.0.0.211
Windows XP, Vista, 7, 8.x and 10
Timeline
27-03-2016: Vulnerability reported to Adobe PSIRT.
28-03-2016: Adobe acknowledges the vulnerability and assigns it PSIRT-5019.
10-04-2016: Requested status update. Adobe replies various mitigation options are being evaluated.
26-04-2016: Requested status update. Adobe replies it plans to introduce a new sandbox security policy: the local-with-filesystem sandbox will be disabled by default. Adobe expects this policy to arrive in Flash Player in Fall 2016.
13-09-2016: Adobe fixes the vulnerability in Flash Player 23.0.0.162.
05-02-2017: Vulnerability published.
Tags: vulnerability research  adobe flash  smb