W3C home > Mailing lists > Public > www-style@w3.org > October 2011

Re: [css-shaders] security - timing attacks

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Thu, 20 Oct 2011 14:31:46 -0700
Message-ID: <CAAWBYDD9wsB_tXxnu=YkqrU846Lx=bcFK1ZWR=gVvLB=pXSpyw@mail.gmail.com>
To: Chris Marrin <cmarrin@apple.com>
Cc: "Gregg Tavares (wrk)" <gman@google.com>, www-style list <www-style@w3.org>
On Thu, Oct 20, 2011 at 10:22 AM, Chris Marrin <cmarrin@apple.com> wrote:
> On Oct 18, 2011, at 4:02 PM, Tab Atkins Jr. wrote:
>> On Tue, Oct 18, 2011 at 10:11 AM, Gregg Tavares (wrk) <gman@google.com> wrote:
>>> Don't CSS shaders end up exposing the same timing attacks for reading images
>>> that WebGL used to before CORS support was added?
>>> Basically, build a shader that takes more time depending on the pixels. Use
>>> requestAnimationFrame to time how long compositing took, adjust until you
>>> overflow a frame. You can now read pixels.
>> Specifically, if you use a shader that runs either at 60fps or 30fps
>> based on what it's run on, you can use rAF to extract, on average,
>> about 45 bits/second of data from any element on the page, potentially
>> including things like cross-origin iframes.
> The difference between the timing attacks that have been shown for WebGL and 2D Canvas is that you're actually making a drawing call and you can time that. CSS renders with the rest of the page, so the time it takes a particular filter to run is hidden in the rest of the page rendering. It seems like the best you could do would be to make several attempts at getting the shader to fall from 60 to 30fps. And then do that at least 3 times and average to take into account other system activity that could make you drop a frame from time to time. So I'd put the number of bits captured at something much closer to 3 bit per second. That would take 80,000 seconds or 22 hours to capture a 100x100 pixel RGB block. Maybe you could optimize from that and get enough info for an exploit with fewer bits per pixel.

Well, if you're repeating each measurement 3 times, you'll average
about 10 bits/second.  You can still OCR an account number with a
known font and location on the page in several seconds.

> Remember too that for WebGL and Canvas2D all this pixel phishing can be done in secret, in a non-visible buffer. But if you tried to do a CSS filter exploit off-screen, most browsers would optimize the render away. So while you're capturing bits the element would have to be visible and the user would see tons of annoying flashing. I don't think most users would sit around and let such an exploit like that run. Add to that the fact that the rendering models of different browsers on different platforms are wildly different. You'd need to tune the exploit to a particular combination of browser, version, platform and machine. That just doesn't seem like a practical exploit to me.

Good point that it needs to be on-screen.  It wouldn't necessarily be
visible to the user, though; the filter can be a visual no-op, since
the information is being passed out via a timing channel.

> Some would argue (reasonably) that even one bit of leaked information is too much. But I believe that this type of exploit isn't something we to worry about.

I agree that one leaked bit isn't a big deal.  A hundred leaked bits,
if they're exactly the right bits, can be enough information to commit
identity theft.  This scenario really depends on a pixel shader having
access to the pixels of cross-domain iframes, though.  If we just
blanked the element's rectangle before giving it to the shader, that
attack would be defeated.  The remaining leakage is probably small
enough to not worry about, you're right.

Received on Thursday, 20 October 2011 21:32:33 UTC

This archive was generated by hypermail 2.3.1 : Monday, 2 May 2016 14:38:51 UTC