WebAssembly has been promoted for its security benefits, though researchers in Belgium and New Zealand contend applications built in this binary format lack important protections.
WebAssembly, or WASM, is a bytecode language produced by compiling source code written in languages like C/C++ and Rust. These output files are designed to run in both web and non-web environments and to do so in a sandboxed environment that’s safely isolated from the host runtime. In effect, it allows developers to build and ship platform-independent applications that, say, your browsers can efficiently run.
WebAssembly’s documentation describes the format’s security goals, and boasts of its memory safety protection.
“[T]he presence of control-flow integrity and protected call stacks prevents direct code injection attacks,” the WASM website explains. “Thus, common mitigations such as data execution prevention (DEP) and stack smashing protection (SSP) are not needed by WebAssembly programs.”
Not so, say Quentin Stievenart and Coen De Roover, from Vrije Universiteit Brussel in Belgium, along with Mohammad Ghafari, from the University of Auckland in New Zealand.
In a paper titled, The Security Risk of Lacking Compiler Protection in WebAssembly, distributed via ArXiv, the technical trio say that when a C program is compiled to WASM, it may lack anti-exploit defenses that the programmer takes for granted on native architectures.
The reason for this, they explain, is that security protections available in compilers like Clang for x86 builds don’t show up when WASM output is produced.
“We compiled 4,469 C programs with known buffer overflow vulnerabilities to x86 code and to WebAssembly, and observed the outcome of the execution of the generated code to differ for 1,088 programs,” the paper states.
“Through manual inspection, we identified that the root cause for these is the lack of security measures such as stack canaries in the generated WebAssembly: while x86 code crashes upon a stack-based buffer overflow, the corresponding WebAssembly continues to be executed.”
For those not in the know, a stack is a structure in memory used by programs to store temporary variables and information controlling the operation of the application. A stack canary is a special value stored in the stack. When someone attempts to exploit, say, a buffer overflow vulnerability in an application, and overwrite data on the stack to hijack the program’s execution, they should end up overwriting the canary. Doing so will be detected by the program, allowing it to trap and end the exploitation attempt.
Without these canaries, an exploited WASM program could continue running, albeit at the bidding of whoever attacked it, whereas its x86 counterpart exits for its own protection, and that’s a potential security problem. Stack canaries aren’t a panacea, and they can be bypassed, though not having them at all makes exploitation a lot easier.
And these issues are not necessarily a deal-breaker: WASM bytecode still exists in a sandbox, and has further defenses against control-flow hijacking techniques such as return-oriented programming.
But as the researchers observe, WASM’s documentation insists that stack-smashing protection isn’t necessary for WASM code. The three boffins say their findings indicate security assumptions for x86 binaries should be questioned for WASM builds and should encourage others to explore the consequences of this divergent behavior, as it applies both to stack-based buffer overflows and other common security weaknesses.
“The divergences exposed here therefore mean that the WebAssembly binaries are exposed to stack-smashing attacks in the sense that, even though the program remains sandboxed in its environment, the control or data flow of the program may be exploited by an attacker,” they conclude. ®