Hacker News new | ask | show | jobs
by kevingadd 3140 days ago
You don't need to escape a sandbox when the application has access to all the user's data.

The attack surface of a gmail implemented in C++-compiled-to-wasm is almost certainly going to be larger than a gmail implemented in JS, because the runtime environment is vulnerable to double frees and heap corruption and other attacks, even if it won't escape the browser sandbox. My gmail tab basically has access to my entire life.

1 comments

I don't understand. In the gmail example, the attack surface to who, a malicious email sender? As in something being handled by wasm in the browser has a better chance at XSS than if it was handled with JS? Why would untrusted content like that be handled by a client-side language anyways? Whether it is wasm, JS, wasm-interpreted-by-a-JS-interpreter, JS-interpreted-by-a-c++-intrpreter, wasm-interpreted-by-a-c++-interpreter or whatever the risks are similar. If you are talking about untrusted wasm or JS scripts accessing things inside the same sandbox, that's a different vector and it's less about the size of surface area and more about the introduction of the vector in the first place.
Simple example (though not something I think the Gmail team would actually ship): I want to load a .png file that's attached to an email. If I decide to use a build of libpng I control (for example, to work around broken color profile support in browsers), a bug in that libpng build could allow privilege escalation within the tab to get access to my gmail contacts or send emails. Bugs in loaders for image file formats are not unheard of, and people treat image files as innocuous.
Ah that example makes it clear. I'll ignore the obvious issue of libpng being written in JS having a similar problem. So the libpng WASM would have its memory instance (probably imported from the caller) and functions would reference the memory. It's not like with regular RAM where if you overflowed a mem write that it would write executable instructions. Code is different from memory. There is no eval. There is a "call_indirect" which can call a function by a dynamic function index, but what would a dangerous function that libpng imported? You can't execute memory or anything.

I can see some site DOSing though where you use the equivalent of a png-bomb to blow up CPU from the parser, but that is any not-meticulously written client-side parser of untrusted input.

So while you can toy with memory and maybe even affect the function pointer before a successive indirect call, it's not near as dangerous to the outside-of-wasm world as raw CPU instructions. I can see an issue where the caller that imports libpng and exports his memory to it might have something secret in that memory...hopefully multi-memory and GC-like-structs and what not can make passing and manipulating large blocks more like params than shared mem (and all of shared mem's faults).

It's a bit extreme but the reality is that a lot of production libraries tend to pull in imports that are as dangerous as eval, because the scope of the library is enormous, or it's actively supposed to interact with the DOM or JS. At that point, if someone can more trivially exploit it with a double free or buffer overflow, you've increased your security risk relative to JS (because overflowing a Uint8Array is basically never going to result in arbitrary function invocation)

The way function addresses are sequential in wasm tables (and deterministic) also means it is probably easier to get to the function you want once you get code execution.