We at Forcepoint have recently touched on the topic of WebAssembly (also known as WA or Wasm). Part of this effort was discussed briefly in an earlier blog post on in-browser coin mining. Today we are going to talk more about the basics of Wasm, and discuss some of the security implications of this new technology. More posts will follow in this series. Later, we will make another post on reverse-engineering a basic Wasm file.
What is Wasm?
As programs made in high-level languages such as C/C++ can be compiled to Wasm and then run in a browser, this gives new possibilities when porting existing desktop applications to web based versions.
Wasm runs in a sandboxed execution environment usually, but not necessarily, within a browser. Wasm is a work in progress, and is constantly being developed. Version 1.0 of Wasm, described as a ‘Minimum Viable Product’ (MVP), was released in March 2017 with support from all major browsers (Chrome, Safari, Firefox and Edge).
WASM IN A BROWSER CONTEXT
Figure 1: Wasm declared in array of bytes and then instantiated.
While Wasm can be written in languages such as C/C++, it cannot by itself interact with the environment outside its sandbox. Even an operation such as printing text to the screen requires having some environment around the application where the text can be printed, whether it be a console, a canvas, a browser or something else. This means that when a Wasm application wants to print a text, it needs to call a function that the browser provides, and the browser in turn will print the text somewhere.
WASM MEMORY HANDLING
This means that within a browser, a Wasm application cannot just call anywhere it wants. The receiving end has to be ready to receive a WebSocket connection, meaning that outbound connections effectively have to be wrapped in an HTTP request. This was discussed in depth in our blog post on in-browser miners.
Detection of Wasm files
Figure 2: Wasm header in hex editor.
Much as with PE files, this header is generally a reliable way of identifying Wasm files.
- new WebAssembly.Instance(...)
See Figure 1 further up for an example of using the WebAssembly.Instance() function.
Wasm security model
The security model of Wasm has the following declared goals:
- Protect users from applications having vulnerabilities due to inadvertent bugs.
- Protect users from applications that are purposely written to be malicious.
- Provide developers with good mitigations against exploitation.
To this end, there are several features designed-in to Wasm that work towards meeting these goals:
- Function calls cannot be done to arbitrary addresses. Instead, functions are numbered, and their number is an index in a function table.
- Indirect function calls are subject to a type signature check.
- The call stack is protected, meaning it is not possible to overwrite a return pointer.
- Control-flow integrity is implemented, meaning that calling a function that is unexpected is going to fail. Expected and unexpected paths of execution are determined at compile time. This makes it hard to hijack the control flow of a Wasm application.
These exploit mitigations go a long way with protecting a Wasm application against abuse. However, the protections are not 100% watertight (few are), and there are conditions that can nevertheless be exploited in some circumstances.
Potential security issues with Wasm
There are several potential security issues to consider with Wasm.
Firstly, as with the implementation of any new feature, the attack surface of a browser has increased: there is a real risk of implementation bugs in Wasm support that may give attackers the opportunity to execute code in a victim’s browser.
Secondly, Wasm applications themselves are potentially exposed to some (but not all) of the vulnerability classes seen in native applications. This is a particular possibility for applications cross-compiled from pre-existing codebases with only minor modifications to allow them to work within a browser framework.
Thirdly, there currently is no way to do integrity checking on Wasm applications. This means that there is no process for verifying that a Wasm application has not been tampered with.
Potential malicious Wasm applications
Despite a Wasm design goal of protecting users against malicious applications, threat actors still have a lot of opportunities. Let us take a couple of examples.
Due to Wasm being a rather new technology, there are not many publicly available tools for analyzing Wasm binaries. Similarly, hardly any documentation exists on how to analyze a Wasm application at this time. This means that, largely, an unknown Wasm application can be a bit of a black box to a human analyst. The researcher may need to resort to analyzing only the network traffic, without being able to understand the inner workings of the code. We expect the situation to improve with time though, as more tools and documentation is released.
WebAssembly is an interesting technology, especially for developers looking to create performance-intensive programs that run platform-independently in browsers (e.g. games).
Forcepoint take a combinatory approach to detection and blocking of coin miners associated with compromised websites, blocking the instances of the scripts which we identify but – more critically – blocking the WebSocket command/relay servers which entire campaigns depend on.
Those interested in looking at Wasm in further depth should take a look at our follow-up blog post available here.
Thus, Forcepoint customers are protected against this threat at the following stages of attack:
Stage 5 (Dropper File) - Malicious files are prevented from being downloaded.
Stage 6 (Call Home) - Attempts to contact the C2 server are blocked.
Start page for Wasm information: https://webassembly.org/
High-level Wasm concepts: https://developer.mozilla.org/en-US/docs/WebAssembly/Concepts