Sidechannel pixel-stealing attack works in Chromium on all modern GPUs
arstechnica.com
arstechnica.com
Here's how it works: a stack of SVG filters is created. These filters are constructed so that they will tend to be faster processing a dark pixel than they will be processing a light pixel.
An iframe is loaded up by the attacking site, pointing at, say, a banking site or some other target of interest. I couldn't find exact details, and my HTML skills are rusty, but I assume the iframe is a 1x1 pixel iframe, and given a pixel offset.
The SVG stack is loaded onto the iframe using CSS, then unloaded, then loaded, etc. a whole bunch of times, and average timing results are assessed. Based on these average times, the pixel is marked 'dark' or 'light'. Repeat for each pixel.
Average time per pixel is in the 1-2 second range. Per pixel. So, this is a slow attack. It could probably get an order of magnitude faster with a sort of combo of zooming and greyscale heuristics that resolves over time, though.
They have a number of cool graphs showing the broad spread of times, and it does look easy to distinguish; their success varies by architecture, but it's over 96% for almost every architecture they test. They show it works while multiple videos and other things that tax the GPU are playing.
Proposed fix: let browsers tell the GPU they need some variant of constant-time processing for an iframe. Which is super, super gross.
Safari and Firefox don't currently allow cross-site iframe injection, so the attack only works on Chromium-line browsers.
Again, eww. And, wow!
Something I didn't understand from my skimming of the paper, though: does this side channel only apply to windows/iframes within the same browser? Why couldn't it apply to windows of different apps? If the GPU rendered a frame buffer somewhere on the screen, then is that exposed by the attack, regardless of whether it's within the browser? e.g. could Chrome.app identify some pixels from a PDF open in Preview.app?
I think this side channel partly relies on being able to stack the iframe on top of attacker-controlled image content. Preview.app will be at an unknown position on the screen, and the Chrome.app window could also be at any position and move, so it's much harder to imagine a way to apply this attack in that scenario.
On the other hand, it would be more effective in reverse, i.e. to require iframed sites to opt-in to allowing host sites to apply SVG/CSS filters to them. Sure, this would break backward compatibility. But who cares? What is the reason for the strong attachment to SVG filters on iframes? Is this a common use case? When is it beneficial?
For the other described prerequisites of the attack, like allowing embedding iframes with third-party cookies inside them, I understand the use case (although if we're being honest this is mostly because of Google wanting to retain YouTube tracking). But SVG filters on iframes? Really?
Most sites don't need any of these features so why not make them opt-in and per-site?
Why/how is that a thing? I know I'm ignorant, but I would natively expect the processing to be a deterministic series of mathematical operations that don't really care what values get fed through.
Edit: Is it something about branching to to handle an upper/lower bound?
Link to original paper:
Axons Law - Any sufficiently fast optimisation will be repurposed as an attack vector.
Seriously though, it's distressing how we have Spectre and Meltdown and whatnot. We've gone too far trying to squeeze every drop of performance out of hardware (Electron is for balance, of course /s) and now we pay the price.
Apparently the other browsers went with "don't inject untrusted third party code into a site".
i.e. the display list for the page has some boxes for iframes, and those boxes are identical to the rasterizer regardless of what origin they're from, so it happily applies filters to all of the iframes.
As for your second point, how is this not a vulnerability in the browser? The security intent is clear, a page should not be able to inspect an iframe. I can’t take a screenshot and read the pixels of the iframe. The fact the chromium supports a published standard is irrelevant. The browser exposes information it is not supposed to and is vulnerable to attack.
The intent of the css feature was not to allow reading iframe pixels. If that cannot be avoided, then the feature is insecure and any browser implementing it has a vulnerability. If it can be avoided then chrome has an insecure implementation.
Browsers have been making use of GPUs for a long time. It's faster than the CPU and saves battery
I think it would be fair to call it an oversight that Chromium allows cross-origin use of the features involved in this attack, but it doesn't really feel like a vulnerability in the traditional sense to me - everything is working as intended/specified AFAIK. It just happens to expose a timing attack. The reality is that tons of things are potential timing attacks and if every single feature that might get used for one was disabled in advance the web platform would be pretty useless.
There are various constraints you could apply to make attacks like this harder - i.e. limiting filter stacks to say 4 items, limiting use of filters cross-origin - but I find it understandable that such things didn't happen. This functionality is probably also quite old so it's possible nobody was taking timing attacks quite as seriously back then.
I feel like the web platform would be much more useful if I didn't have to constantly worry about drive-by attacks leveraging bugs in a giant stack of "web technologies" that are only getting more complex with each passing year.
> On AMD’s Ryzen 7 4800U, GPU.zip took about 30 minutes to render the targeted pixels with 97 percent accuracy. The attack required 215 minutes to reconstruct the pixels when displayed on a system running an Intel i7-8700.
Preprint paper: https://www.hertzbleed.com/gpu.zip/GPU-zip.pdf
Not saying to make this achievement smaller than it is, quite the opposite, it's important there is more such research.
||*^$subdocument,third-party
Piracy is the odd-one-out because it's about "stealing" non-secret information, which seems non-sensical.
I expect they're not often visible, though.
This attack might be too slow as long as I hide the password within 30 seconds, but future versions of the attack might be fast enough to capture multiple characters, especially if the malicious website hosting the iframe knows which pixel positions will be occupied by the password box.
e.g. If you take someone's car while they're away on vacation and bring it back before they get home, it is still stealing, even if you topped up the tank and they never noticed.
The reason that it is wrong to take my car, even if I don’t notice, are multiple:
- You are still depriving me of the possibility of using my own car, even if it happened to be the case that I didn’t need it. I could have come home early. I could have told some friend or family to pick up my car so that they could use it. I could have had an appointment that someone would come by to service my car while I was absent. All of this is made impossible if someone takes my car.
- It still causes wear and tear on my car if you use it.
- You could get into an accident, which could hurt you and damage my car.
- I don’t want random strangers to sit their butts in my car.
- etc
"They stole my idea"
"He stole my identity"
> You could get into an accident, which could hurt you and damage my car. - You could have a data breach, which could hurt you and damage my privacy
> I don’t want random strangers to sit their butts in my car. - I don't want random strangers to put their eyes on my private browsing
> etc - etc
* User preference (E.G. plugins/extensions)
* Native to the site, when a user is logged in
* Trivial and sandboxed to page local data
I recall how I used to use Flash, with a plugin that delayed the loading until AFTER I hit 'play' on the plugin frame.I suspect that's the sort of security framework that will solve a lot of the problems. Do not run untrusted code by default. Have the user to enable a site (often during account creation / sign in on a new device). Have the user 'click play' if they expect something to work.
Make sites that just work without client side code again.
If I want to run something on my computer I’ll damn well download a tar file and spend several hours arguing with autoconf! :)