(NOTE: This article has been sitting in my drafts since May 2014. I am very lazy.)
Flash only allows read access to the clipboard in event handlers triggered by
paste events, but Flash wasn’t checking if the clipboard contents had changed since entering the event handler. Due to quirks in how Flash’s event handlers work, an attacker could read from and write to the clipboard for hours after the user navigated away from page containing the SWF, even after navigating away or closing the incognito window.
All that messing around with Flash in my previous posts made me think that I should read more into Flash security. Even if you hate Flash as a user, it’s deployed pretty much everywhere and it’s valuable attack surface! It ended up paying off, after a couple days of testing and reading the docs, I was left with a new bug, CVE-2014-0504:
Let’s go into the combination of issues and possibly surprising behaviour in Flash that allowed clipboard leaking.
User-initiated actions and clipboard access in Flash
This isn’t the first time Flash has had issues with clipboard access. Back in the days of Flash 9, you could write to the clipboard with no interaction at all. That caused a few problems, so when Flash 10 rolled around, Adobe added a few restrictions to clipboard functionality:
First, the new
Clipboard API only allowed writing to the clipboard when inside certain event handlers (
Second, that event handler had to have been triggered by user interaction, meaning that event handlers triggered by
dispatchEvent et al. cannot write to the clipboard.
1 2 3
Additionally, a method allowing you to read from the clipboard was added. This was restricted even more, and could only be called inside user-initiated
1 2 3 4
Overstaying our welcome
We’ve established that to call
Clipboard.getData we must be in a
paste event handler, and that handler must have been triggered by the user. As far as I can tell, there’s no way around that. Can we still abuse it?
The obvious thing to check is if we can block inside the event handler. In many browsers, blocking in an event handler in Flash will cause a plugin hang, and a prompt to kill the plugin will spawn. Chrome, however, keeps right on trucking, even when Flash is executing something like
Enjoying the view
Given that we aren’t really penalized for sitting around in a privileged event handler, there’s nothing to stop us from just calling
Clipboard.getData() in a loop and checking for changes. We can just get the user to paste something non-sensitive, then abuse our clipboard access to read sensitive information that gets added to it later.
Here’s a basic demonstration of the issue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Roadblocks to real-world exploitability
Getting the initial paste event
To trigger the exploit, we need to convince the victim to paste something into our SWF. There are a number of usage patterns we could abuse to do that, but I liked the fake captcha method kkotowicz used for his cross-domain content extraction attack. We give the user a random string, and ask them to paste it into “verification box” (actually our SWF,) telling them it’s required to prove they’re not a bot:
Flash will not allow a single event handler to run for longer than 60 seconds. A 60 second window for clipboard access is obviously not ideal for us.
Luckily, the time limit is on individual event handlers, and the paste event bubbles. We can just give our paste target tons of parent elements that also handle
paste events, and allow the event to bubble up before the handler gets killed, Then we can log the clipboard for
60~ seconds * \<num of parents\>:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Leaking clipboard contents to a remote server
1 2 3
ExternalInterface method has the caveat that it will longer work after we’ve navigated away from the page or the tab was closed, even though our event handler will continue to run. As a fallback, we can use Flash’s TCP socket support, which allows synchronous communication. Again, with a caveat that it only seems allow sending a single message while in the event handler 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Going the extra mile
So we can leak the clipboard remotely even after navigating away. That’s neat, but we can actually do a lot more! Remember how Flash allows us to write to the clipboard in certain handlers as well? That lets us do all sorts of sneaky things, like detect when someone copies what looks like HTML, and then modify it to include a malware script. Even better, we can detect clipboard contents that look like commands and slip our own payload into them!
1 2 3 4 5 6 7 8 9 10 11 12
The code for a full PoC is here, and a live version without the echo server is also up here.
The initial fix was to expose a sequence number to Flash so it could tell if the clipboard state had changed since the initial event was raised, and block access to the clipboard. That stayed in place for a while, but some time after that it was replaced with a change that blocked clipboard reads 10 seconds after the event was raised. If I had to guess why, some application probably relied on being able to do multiple clipboard reads and writes in the same event handler.
Being able to read the clipboard 10 seconds after the initial paste event still seems a bit much, but it’s definitely better than how it was before.
- Flash event handlers may continue to execute up to two hours after starting, even after closing incognito windows!
Socketclass is useful something other than bypassing the user’s proxy!
- Flash still has low-hanging fruit to be picked, and its stdlib is absolutely enormous. There aren’t many eyeballs on it either, you’re only really competing against Masato Kinugawa :)
- 2014-01-06: Disovered the bug
- 2014-01-09: Reported to Google’s sec team due to it mostly affecting PPAPI Flash
- 2014-01-09: Bug confirmed by Google’s security team
- 2014-01-13: Bug confirmed by Adobe’s security team
- 2014-01-29: Google ships code exposing the clipboard sequence num to Flash via PPAPI
- 2014-03-14: Adobe ships a fix to use Chrome’s clipboard sequence number
- ???: Flash switches to allowing clipboard reads for 10 seconds after the event is raised
Firefox on Linux demonstrates similar behaviour, but allows Flash’s event handlers to continue executing even after the browser has closed.↩
Again, Firefox on Linux behaves differently. You can send / receive as much as you want, even after the browser has closed. It’s possible that Chrome’s behaviour is a bug.↩