[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Proposed change to WebGL spec section 4.2 (Security Origin Restrictions)



2010/10/6 Steve Baker <steve@sjbaker.org>:
> Brian Cornell wrote:
>> If I understand the WebGL shader limitations correctly, you black hat
>> solution would not work because loops that can't be statically
>> unrolled are not allowed. So you could not use a loop based on the
>> texel value.
> If you did a pixel 'discard' inside an 'if' statement many modern cards
> would do an early-out of the shader if all of the adjacent pixels
> terminated early.  No amount of legalese in the spec will prevent that
> from happening if that's what the hardware actually does:
>
>     for ( i = 0 ; i < 256 ; i++ )
>        if ( i > texelBrightness*255 )
>           discard ;
>        else
>            read a random texel out of a huge map ;
>
> But it doesn't matter...I just thought of something even easier.  Even
> if the vertex and pixel shaders take absolutely the same amount of time
> no matter what - I can STILL just do this at the end if the vertex shader:
>
>      gl_Position = vertexPosition.xy * texelBrightness ;
>
> ...then I bind the texture to a vertex shader sampler and draw a large
> quad in the center of the screen.
>
> The size of the quad will be proportional to the square of the texel
> brightness - and the number of pixels we'll draw will be roughly
> proportional to the brightness - and with finite frame buffer memory
> speeds that's got to impact the pixel processing time in a sufficiently
> predictable way for this hack to work.   For a useful exploit we might
> only need to be able to read a 100x20 texel patch of white text on a
> black background and we've stolen someone's credit card number.  You'd
> only need to distinguish black from white...a simple timing threshold
> would suffice.  Text is pretty readable even in the presence of
> considerable noise - so random timing variations would be little
> obstacle to the determined bad guy.
>
> So there are plausible exploits even with readTexels and occlusion
> culling completely disabled.

Some analysis on this timing attack:

The hole is that an attacker can read back bits from a non-Same-Origin
image with a known URL at a rate dependent on timer resolution. The
cause is that the execution time of a draw command can be made
dependent on a bit in a non-SO texture. The fix is to either ban
non-SO textures from WebGL or make draw commands on a non-SO WebGL
context take the same time regardless of texture contents.

The impact of this attack is kinda low for normal images (attacker
would have to know the URL of the image but not the contents, so the
target is some kind of dynamically generated image with a
static/guessable URL and contents dependent on session cookie). If you
have stuff like SVGs with foreignObject usable as textures, it's a lot
worse.

Off the top of my head, it's somewhat doable to secure the shaders.
Tag a fragment shader unsafe in the validator if it has branches or
writes to gl_FragDepth (to attack early-z). Tag a vertex shader unsafe
if it has texture reads. Tag a program unsafe if any of its shaders
are unsafe. Throw a security error on draw command if an unsafe
program is bound on a non-SO context (or if an unsafe extension like
occlusion queries is enabled).

Alpha test happens after the fragment shader AFAIK, so I think it
shouldn't have an effect on the execution time. Are there other
possible leaks? Ways to use texture values to control the amount of
fragments a fragment shader is called on.

--
Ilmari Heikkinen

-----------------------------------------------------------
You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email: