Security Sandcastles — Hardening workloads and resources on WASM

Imran Roshan
Google Cloud - Community
5 min readJan 18, 2024

--

Making security easy for near native performance environments

How cool would it be if you can get the performance of native systems in the fraction of the computational expense and the hassle of the tedious setups and maintenance?

WebAssembly (WASM) has transformed web development by enabling the browser sandbox to achieve near-native performance. But as web apps get more sophisticated and complex, it becomes more important than ever to secure workloads and resources in WASM environments. Let’s have a lood and explore potential threats, the security landscape of WASM, and tactics to protect your priceless sandcastles from the digital sandstorm.

A little primer on WASM

General Bookish Definition

WASM is a compiled, low-level, stack-based language made to run quickly in web browsers. Its bytecode format makes integration with JavaScript easier and allows for platform portability.

Two components comprise WASM modules:

Linear Memory: Data and code segments are stored in a byte array called linear memory.
Exports and Imports: Functions exposing functionalities to and receiving services from the JavaScript host environment.
This division allows WASM modules to use JavaScript for DOM manipulation and user interaction, while still enabling them to safely carry out complicated computations.

The Threat Landscape on WASM

Although WASM has many benefits, there are still security risks to be aware of:

  • Memory Corruption: Information leaks, heap overflows, and code injections can result from taking advantage of WASM’s linear memory.
  • Integer Overflow: Unchecked math operations have the potential to overflow, invalidating memory pointers and permitting arbitrary code execution.
  • Type Confusion: Misunderstanding the different kinds of data can result in unexpected actions and possible security lapses.
  • Side Channel Attacks: An attacker may be able to obtain private information from WASM’s execution patterns by using astute timing analysis.

If these flaws are taken advantage of, they could jeopardize private information, interfere with operations, and even take control of user sessions.

Now we secure

Workload security for WASM demands a proactive and watchful approach. We can make sure our sandcastles survive the digital storms and function with confidence in the constantly changing web landscape by implementing strong isolation techniques, utilizing specialized WASM security tools and a layered approach!

Secure coding practices

Memory Management: Make sensible use of memory allocations and deallocations. Take into account libraries for automatic memory management such as sm) that collect garbage.

  • Memory Model: WASM has a linear, contiguous memory model. It’s a single, shared memory space accessed by both WASM code and the host environment (JavaScript).
  • Manual Management: WASM doesn’t have automatic garbage collection. You’re responsible for explicitly allocating and deallocating memory.
  • Pages: Memory is organized into 64KB pages. You can grow memory dynamically, but there’s a maximum limit of 4GB.

For example simple memory allocation and deallocation looks like:

// Import memory from the host
use std::alloc::{alloc, Layout};

// Allocate a block of memory
fn allocate_memory(size: usize) -> *mut u8 {
let layout = Layout::from_size_align(size, 1).unwrap();
let ptr = unsafe { alloc(layout) };
// ... initialize memory if needed
ptr
}
// Deallocate a block of memory
fn deallocate_memory(ptr: *mut u8, size: usize) {
let layout = Layout::from_size_align(size, 1).unwrap();
unsafe {
std::alloc::dealloc(ptr, layout);
}
}

Type Checking: Enforce type safety using tools like wabt wat2wasm or pyodide for WASM python interaction which offers stricter type checking than the standard compiler.

Now I am familiar with python where a type check would look something like

# Example 1: Checking for integer arguments
if isinstance(arg1, int) and isinstance(arg2, int):
result = add_func(arg1, arg2)
else:
raise TypeError("Arguments must be integers")

# Example 2: Checking for specific types in a more complex function
def check_types(func, expected_types):
if len(func.params()) != len(expected_types):
raise TypeError("Incorrect number of arguments")
for i, param in enumerate(func.params()):
if param.kind != expected_types[i]:
raise TypeError(f"Argument {i+1} should be of type {expected_types[i]}")

# Example usage:
expected_types = [wasmtime.ValType.i32, wasmtime.ValType.i32] # For two integers
check_types(add_func, expected_types)

Exception Handling: To reduce unexpected behaviour and avoid crashes, implement strong exception handling.

A simple exception handling for runtime errors as a continuation for the above type check would be:

try:
result = add_func(arg1, arg2)
except wasmtime.Trap as trap:
print("Trap occurred:", trap)

Some WASM Specific techniques

Bounds Checking: To stop heap manipulation and buffer overflows, implement bounds checking on memory accesses.
Control Flow Integrity (CFI): To stop code tampering and hijacking, use sophisticated CFI techniques such as SWC’s wasm-opt with the — cfi flag.
Secure Enclaves: Look into technologies that offer hardware-backed isolation for sensitive computations, such as AMD SEV or Intel SGX.

Sandboxing and Isolation mechanisms

Import restriction: Limit the WASM module’s access to JavaScript APIs, particularly those that are sensitive like file system access, by using restricted imports.
Resource Quotas: To stop resource exhaustion attacks, enforce resource quotas on memory usage, CPU utilization, and network bandwidth.
Content Security Policy(CSP): Employ CSP headers to limit the execution of arbitrary WASM modules and guarantee that only approved modules are loaded. CSP stands for content security policy.

Security Toolsets

Here’s a list of some security toolsets that you can use to secure your WASM resources:

Static Analysis

  • wapti: This strong tool looks for possible flaws in your WASM code, such as type confusion, integer overflows, and memory errors. It provides thorough reports and remediation recommendations.
  • OSS-Fuzz: This open-source fuzzing framework uses a plethora of malformed inputs to your code in order to uncover hidden vulnerabilities. It integrates with a variety of WASM compilers and libraries.

Runtime Monitoring

  • wispr: Abnormal activity in your WASM applications, such as memory violations, attempts to hijack control flow, and unusual resource usage, can be detected by this lightweight runtime monitoring tool. It assists you in identifying possible security breaches before they become more serious and offers real-time alerts.
  • WASI Monitor: Applications operating in the WASI (WebAssembly System Interface) sandbox can be observed with the aid of WASI Monitor. It monitors memory, CPU, and network resource usage and offers insights into possible attacks involving resource exhaustion.

Secure Enclaves

  • Intel SGX: Your WASM applications can have separate execution environments for sensitive calculations thanks to this hardware-based technology. It provides an additional degree of security for cryptographic operations and important data.
  • AMD SEV: Your WASM workloads can benefit from a similar degree of security and isolation for enclaves thanks to this analogous AMD technology.

Resources

Honestly, WASM is a world in its definition. Exploring the entirety would give me food for writing blogs for my lifetime. So why stop HERE? Explore the resources to learn and implement your amazing WASM loads.

Connect with me?

--

--

Imran Roshan
Google Cloud - Community

Your security sherpa | Google Developer Expert (GCP) | Ethical Hacker | Cloud Security