You are right, some of the issues highlighted in the paper could be solved by compilers targeting WebAssembly. One such mitigation that is (currently) missing are stack canaries. In contrast, stack canaries are typically employed by compilers when targeting native architectures. They also cost performance there (typically single digit percentages), but evidently compiler authors have decided that this cost is worth the added security benefit, since fixing "old C issues" in all legacy code in existence is not realistic.
Note however, that other security issues highlighted in the paper _are_ characteristics of the language, notably linear memory without page protection flags. One consequence of this design is that there is no way of having "truly constant" memory -- everything is always writable. I do think that this is surprising and certainly weaker than virtual memory in native programs, where you _cannot_ overwrite the value of string literals at runtime.
That said, we always knew a day would come where WebAssembly would get the ability to set more page protections. For non-web embeddings, this is easier, but as of yet, none of the engines I know of have either an API or are really prepared for the implications of this. I am still bullish on eventually getting that capability, though.
Thanks for your paper.
As you said, I just hope page protections can still be added later (somebody needs to specify it, embedders need to be able to implement them, toolchains need to pick it up, etc.).
Maybe memory vulnerabilities inside WebAssembly programs can also be mitigated in other ways that do not require such pervasive changes, e.g., by keeping modules small and compiling each "protection domain" (e.g., library) into its own module, or to have a separate memory. I am not sure about the performance cost of such an approach, though.
That is not true. As the paper goes into depth, linear memory, lack of ASLR, and the lack of read-only memory are problematic regardless. The latter is the most important imo.
I agree it makes Rust more attractive than C for WebAssembly.
But the original demos for WebAssembly were all in C, not Rust (games like Doom IIRC). The thing that made it attractive in the first place is that you could run existing code, e.g. image processing or machine learning in C/C++.
That's because the way you're using secure is likely misleading to most people; two WASM programs will be more strongly isolated from one another than two normal programs. The host has better protection from a WASM program than a C program. Those protections are akin to a VMs, but likely better.
The protections that are missing aren't irrelevant, but likely less relevant than in an OS context because WASM's I/O is so heavily constrained. Malicious data is still a possibility, but not quite as trivially triggerable as in any other networked program. Similarly, once hacked, those same limitations make the scope for mischief much, much more limited.
Sure, there are attacks conceivable against a WASM program that couldn't work when protected by various defenses in depth available to a "normal" OS program, but the reverse is true too - if you will; the scope of bugs is much, much smaller in WASM, but within that limited scope they'll be more easily triggerable. However, since the scope is so limited, I have a hard time believing the net effect is negative in practice.
This is wholly incorrect. Two WASM programs will be at most as isolated as two normal programs, but in practice substantially less so. Spectre being the obvious one that sort of "fully breaks" in-process sandboxing, but lack of hardware enforcement also means you're now more vulnerable to host bugs, too.
Regardless it's a question of what is the juicier attack surface. WASM only cares about protecting the host from the embedded code, but it does that essentially by sacrificing the embedded code's own security from the outside world. That is, if A is the WASM host of B, and B can be called by C, then WASM is about protecting A from B at the cost of making B more vulnerable to C. If B is the thing that actually has the juicy data that C wants in the first place, this is a really bad tradeoff. If A is the juicy target, though, then this is a fine tradeoff.
So in a browser context where the host is almost always the juicy target, WASM's tradeoffs work. If, however, you're talking about things like using WASM for web server sandboxing instead of docker or a VM, well the web server itself is likely the interesting attack surface rather than the "hypervisor." So that's probably not a good tradeoff to make there.
By contrast, normal OS programs have all kinds of I/O, including inter-process communication, shared locks, high-res timers, shared memory, files, networking, etc etc etc. Even if those programs are "fairly isolated" by being inside a VM, they still have access to all kinds of low level tools that WASM won;t have that might leak enough entropy to still be less well isolated - and that's kind of necessary and by design, because a VM or container is designed to run largely unmodified binaries, and thus cannot simply omit capabilities legacy programs have - but WASM can, and does. Then there's simply the sheer complexity difference; it's pretty daunting task to have all that be entirely safe.
In essence: there's a reason why it's much more common to see e.g. privilege escalation vulnerabilities than WASM sandbox escapes.
It isn't.
WASM right now is missing all those things because WASM right now is a toy for moderately accelerating JavaScript. If WASM's usage expands beyond that, those feature limitations will rapidly vanish.
If indeed webassembly adds features that add attack surface, I sure hope (and fully expect) them to take things like spectre into consideration.
As to SELinux: the issue with securing existing programs is that those use all kinds of existing features; it's quite hard to take away functionality that programs depend on. SELinux simply has a much harder and trickier task than WASM, which never supported almost everything SELinux seeks to control in the first place. It may well be that it's possible to have SELinux enforce WASM-or-greater restrictions and that it would then be "safer" due to other features, but that's a pretty hypothetical scenario - what software would even run in those circumstances?
The comparison seems moot to me; apples to oranges. One is trying to KISS and be safe by simply not having complex features; the other is trying to deal with real, existing programs by restricting stuff they could access but don't need. Those are different use cases.
You seem to be continually focusing exclusively on the current existing extremely limited WASM-in-a-browser usage.
WASM's current limitations aren't intentional, it's because it's not finished & wasn't necessary for the MVP. In fact, it already has some of the things you are claiming it doesn't have - both threads & shared memory are available already in Chrome & Firefox's stable releases ( https://github.com/WebAssembly/threads/blob/master/proposals... & https://webassembly.org/roadmap/ ). Which means it also has accurate timers.
WASM very intentionally allows the host to expose whatever feature set it wants. That's a very core design element. You can't just ignore that and focus on the ~nothing that the "spec" itself delivers & pretend that's by-design. WASM isn't a standalone runtime and isn't trying to be.
You state WASM's limitations aren't intentional; they just weren't finished - but being able to use those securely is part of being finished, and they weren't enabled in browsers until they were.
Obviously other hosts may do whatever they want. That's a valid hypothetical, but just as valid a hypothetical is that WASM implements relevant defense in depth features before such poorly sandboxed hosts become commonplace; it's not like they're not aware of the issue (https://webassembly.org/docs/security/). Hypothetically it might be "safer" than SELinux; but... today none of this matters, and the missing features don't appear to be intrinsic. It's not like native programs have had ASLR since day 1 either, right? Or maybe WASM stays in the "highly isolated" niche which is fine too, and would still allow various usages outside the browser too (e.g. for most apps that don't interact with other apps outside of a few carefully controlled primitives).
If people make poor choices about future development, things may end up less secure than they are today: sure.
So, on the one hand I can't dispute what your saying - I just think it's not the best thing to be focused on, because a trivial summary would make it seem like there's a real risk in having WASM as it is today, and that's not the case. We should be very careful in the future, yes, but let's not throw out the baby with the bathwater; wasm's portability and sandboxing in practice today are likely quite useful and more secure (in a browser context) than a native app (outside of a browser context).
Innocent and naive as I am, I feel like this shouldn't be true in a post-spectre world? Surely intra-process isolation is recognized as, at minimum, a difficult problem to solve today? The attack surface of your host, given arbitrary compute powers (which wasm has), is quite significant.
It's not to say that intra-process isolation isn't a worthwhile goal, I'd rather see new systems designed with the idea if they can be. I'm just saying I don't know that "unsandboxed but has lots of mitigations" vs "sandboxed but trivially exploitable" is so clearcut.
But even supposing you pull all that off - spectre needs not just some entropy leakage, but also a way to put that entropy in context. Knowing a few random bits in some other processes memory space won't do you much good; you'll need to know something about how that process is working to interpret those bits and target the slow leakage, which is again pretty situational.
Finally, you need some way to check for indirect behavior changes, and typically that means timers. Those aren't directly available in WASM, and aren't as easy to replicate using other means as in a normal process; e.g. wasm doesn't even have fully capable shared-memory threads for exactly this reason (there's a proposal, and chrome feature flag, so you can play with it, but that's it); and other tricks to get reliable timers like via SharedArrayBuffer have been tweaked to avoid attack surface. But note: that's the case for WASM, but not for a classic OS program, even one running in a VM.
I'm not sure how much of a threat spectre is in practice, but clearly WASM is aware of it and avoiding features that would increase exposure, even very valuable stuff like threads.
If it's the first one, I dont think i really care.
But worth adding that Wasm by design lets you statically inspect all the things the Wasm can call. If the Wasm receives access to networking, or eval(), etc., then there is a real risk. However, often the Wasm imports and exports are extremely limited and easy to verify for safety.
Someone who controls the image data can perform an XSS, i.e. steal your credentials for the website, or your credit card info if that's stored server-side. That's not as valuable a target as controlling your computer, but it's not nothing, and can be chained.
This is completely realistic as Figma is full blown image editor written in C++ compiled to WebAssembly :)
https://www.figma.com/blog/webassembly-cut-figmas-load-time-...
If this is the case it mean there is already a hacker or virus running outside the sandbox which mean I already have bigger problem to worry about :).
That said, it does highlight that memory-safe source languages and other program exploit mitigations are still important even in a webassembly sandbox. Personally I wasn't confused about this fact, but it does clarify this point for any that might think that WA == no more security problems in any context.