This blog is intended to be a warning bell and to draw attention to a potential security risk involved in running sensitive applications in the WSL (“Windows Subsystem Linux”) Windows utility.
As reported by Microsoft [here], WSL usage is growing fast (“more than 3.5 million monthly active devices today”). With the enhancements included in the upcoming WSL 2 and the planned improvements in WSL’s roadmap, it is reasonable to expect the usage of WSL to continue growing even faster.
The security risk that I will highlight is not caused by any software bug (in Windows or Linux), nor is it exploited by any new and complicated attack technique. Instead, it is based on simple usage of the WSL utility as it was designed.
If you are using or intend to use WSL, or if you are responsible for the security of endpoint users using WSL, this research is a must-read. As for the rest of you, you may continue reading at your own risk (😉 ) (remember, there are no exploitable bugs or new technical discoveries here).
- WSL is a Windows utility that allows users to run Linux applications under Windows.
- Any standard (non-admin) Windows process has full access rights to all the files that make up the WSL machine.
- If a malicious program runs as this standard process, it can steal sensitive static data (e.g., SSH keys) by simply copying them from the WSL file system.
- By modifying the programs in the WSL file system, our malicious program can also capture sensitive dynamic data (e.g., usernames, passwords, passphrases).
- The WSL design allows the activation of Windows processes by programs running inside the Linux machine. Therefore, a standard (non-root) Linux program can completely take over the Linux machine.
- WSL 2, designed as a “lightweight Utility VM”, has markedly diminished the attack surfaces of WSL, but is still vulnerable to the security weakness described here.
- Bottom line: Running sensitive applications inside WSL is significantly less secure than running the equivalent applications in a standalone Windows or Linux Desktop system.
WSL 2 is now formally released (as part of Win-10 version 2004), and has generated a lot of buzz.
Microsoft has been stating regularly that it “loves” Linux [here], and has lately declared that it will support running GUI Linux applications in WSL [here].
These changes in Microsoft’s attitude and intensive development plans for WSL are an indication of a marked change in the expected usage of WSL. Initially, it was intended to support developers (and possibly security researchers) that want to develop or test Linux applications inside Windows, but now it appears to be a generic Windows utility that allows all user types to run Linux applications in Windows Desktop systems.
WSL 2 is a more secure system than WSL 1 (or the legacy “bash” feature), but it does not eliminate the risks involved in running sensitive applications inside it.
To be clear: It is a well-known fact that the “host” system always has full control over the “guest” system. The real issue here is that the intended usage of the WSL utility will expose many users to a security risk they might not be aware of. This is probably already the case as it appears that quite a lot of WSL users are currently using it to run an SSH client or server or both (programs that process sensitive credentials data).
Searching Google for “Running OpenSSH in WSL” finds some 270,000 results. Of course, not all of these references are relevant, but looking in the first few pages, one can see that most of them do discuss how to install and run OpenSSH Client or Server in WSL, or how to interface the Linux SSH programs with the Windows SSH keys and programs.
Figure 1: Two examples of online references to SSH usage in WSL
The History of WSL
“bash” – First, there was the “bash” feature. A pico-process named bash, launched by a bash-launcher program bash.exe. The bash pico-process emulates a Linux terminal and executed Linux programs – converting Linux kernel APIs to the equivalent Windows kernel APIs. The internal architecture and working mechanisms of Windows’ pico-processes are not relevant to our story.
I am not sure when it first became an integral part of Windows, and I doubt that anyone (except me, of course) is still using the “bash” command, but it is included here for “completeness” sake. If for some reason you are still using it to run sensitive Linux applications such as OpenSSH – beware as it is easy to exploit, as you shall see.
“WSL 1” – For Windows 10, the “wsl” command (wsl.exe initially released in August 2016) replaced the “bash” command. A support utility (wslhost.exe) was also activated, in addition to the bash pico-process.
Since WSL 1 file system infrastructure is very similar to the “bash” application, sensitive applications running in this environment are exposed to security risks similar to applications running under “bash.”
“WSL 2” – WSL 2 was introduced in Win-10 version 2004. The architecture of WSL 2 is drastically different from that of WSL 1. The Linux distribution package is run as a “Lightweight Utility VM” under HyperV, replacing the pico-process technique.
The features of the “Lightweight Utility VM” WSL 2, which are relevant for our case, are discussed later on in this blog, but if you are wondering what exactly a “Lightweight Utility VM” is, an excellent explanation can be found here.
When you run the “wsl” command to activate WSL 2, vmwp.exe (HyperV process) is run instead of the bash pico-process.
A side note: The architectural changes in WSL 2 may aid some attack methods. Connor Morley from F-Secure has published a white paper [here] which analyzes the possibility of weaponizing WSL 2 to achieve a persistent and stealthy attack on the hosting Windows system. Here we examine a much more modest target of “stealing” sensitive information from applications running inside a WSL that has been “legally” installed. Our attack is a “single-shot” event [from the Windows side] that modifies programs/files inside the WSL file system, and no persistence in the Windows side is required.
File System Implementations
“bash” file system
The Linux file system for bash was implemented as an integral part of the Windows file system.
Typically, the root folder for the Linux file system is located for each user at:
The Windows’ security settings for all the files in this folder and all its’ subfolders allow any program that is running in this user’s session full access.
Figure 2: A standard Windows process has full access to a sensitive Linux file (sshd-OpenSSH server)
“WSL 1” file system
The Linux file system for WSL 1 is similarly an integral part of the Windows file system.
Typically, the path to the root folder of the Linux file system for each user is something like:
Like the “bash” case, the Windows’ security settings for all the files in this folder and all its’ subfolders allow any program that is running in this user’s session full access.
Note: The user can control the location where the Linux DISTRO is installed. In some of the POC cases, you will see the rootfs folder at C:\Users\<weak user>\Documents\Ubuntu\rootfs.
“WSL 2” file system
Since WSL 2 is a VM run by HyperV, its’ entire file system is implemented in a single vhdx file such as:
When the VM is inactive, any program that runs in the session of a user for which WSL 2 has been installed has full access rights to this file. Modifying data in this file is possible, although more complex than modifying “bash” or WSL 1 files. In the next session, I will show a simple method to bypass this complexity.
“Seamless” integration with the Windows file system is achieved via a COM object that implements the “Plan 9 File System” protocol (using the new vp9fs.dll). Programs running inside the VM can access Windows files using the prefix “/mnt/c/” in the file name (as was done in “bash” and “WSL 1”).
Windows processes can access Linux files “legally” by adding the prefix \\wsl$\\<distribution-name>\ to the full file name. It is instructive to see that in this kind of access, the Windows’ process does not have any “root” privileges even if it is elevated.
Figure 3: Elevated Windows Process cannot modify a sensitive Linux file “legally”
Attacking Sensitive Applications Running Inside WSL
For the first 3 cases we assume the following preconditions:
– A malicious program is running in a standard process in the Windows session of a user.
– This user uses WSL to run sensitive applications (not necessarily right now).
I discuss attacks on SSH Client and SSH Server programs, but this attack mechanism applies to any sensitive application.
The “bash” POC was done in a Windows-10 machine, version 1909.
The WSL POCs were run in a VM machine (registered for the Windows Insiders program) under VMWare (Windows 10, version 2004, Build 19624.rs_prerelease.200502-1339).
Attack-A: Attacking sensitive applications running inside ”bash”.
This case is straightforward as the attacker always has full Read/Write access to the entire Linux file system . Potential attack actions could include:
a) Stealing Credentials from SSH Client
The ssh command accepts the credentials of the user and passes them on to the server who will authenticate the user.
The SSH Client program (ssh) can be modified so that every time it is activated the following data is “leaked” out to the attacker:
– All command-line arguments.
– An identity file (private SSH-key identified by the “-i” command-line argument).
– A Password that is requested and manually entered.
– A “passphrase” that is requested and manually entered.
In this way, the attacker can accumulate (over time) all the information required to access all the SSH servers to which this user connects.
POC-A: Sensitive program modification (“bash” case)
Figure 4: Inside the Linux environment, the “ssh” program can only be modified by “root”
Figure 5: A standard Windows program modifies ssh (“bash” case)
b) Stealing Credentials from SSH Server
If the user happened to set up an SSH-server in WSL, a significant amount of sensitive information could potentially be leaked out.
One use case for such a server is to enable the user to work from home. He may also use this server to connect to other servers in the organization’s intranet (via “tunneling”).
Note that inside the Linux environment, only “root” Linux users can access the Private SSH keys, but from the Windows side, they are entirely exposed.
Figure 6: Private SSH keys in Linux are “root” protected, standard Windows processes have full access
All the credential information required to connect to this server can be accumulated by:
– Access to the sshd_config file.
– Access to files and folders referenced by the config file (e.g., AuthorizedKeysFile).
– Modifications to the sshd program itself to capture credential information passed dynamically.
By modifying the configuration file (sshd_config), any access limitations defined by the user can be removed (and, of course, any remote connection can be authorized).
c) Exploiting SSH tunnels
The user may set up an SSH Server in WSL and define Port-Forwarding into other servers (again – to support work from home is one possible use case). In this case, the attacker can gain permanent remote access to these servers using the information collected in step “b” above.
Attack-B: Attacking sensitive applications running inside ”WSL 1”.
Since the implementation of the Linux file system is identical to the “bash” case, all the attacks described in Attack-A above are applicable here too.
POC-B: Sensitive program modification (WSL 1 case)
Figure 7: A standard Windows program modifies ssh (WSL 1 case)
Attack-C: Attacking sensitive applications running inside ”WSL 2”.
As mentioned before, the entire file system for a WSL 2 machine is implemented in a single vhdx file. Two issues make it harder to perform the attacks described above on this system:
a) Modifications to this file system are more complicated to implement than modifications to the file system of “bash” and “WSL 1” since you cannot simply open and update the files’ contents.
b) When the machine is active, vmwp.exe has exclusive Write Access to the file.
One simple way to bypass both of the above limitations is to use the WSL version conversion feature:
– Convert the WSL 2 file system into a WSL 1 file system.
– Perform the required modifications to the Linux files.
– Be kind (😉) and convert the WSL 1 file system back to WSL 2 format [optional].
This course of action is achieved by executing a batch with the following console commands:
1: wsl –set-version <distro name> 1
2: <attack program>
3: wsl –set-version <distro name> 2
Luckily [for the attacker], if the WSL 2 VM is currently active, the first command will silently terminate the WSL 2 session (even if user programs such as OpenSSH Server are currently running).
POC-C: Sensitive program modification (WSL 2 case – conversion to WSL 1 and back)
Figure 8: Original WSL 2 state: passwd is a SUID program (Auto-elevating to “root”)
– When the conversion to WSL 1 is initiated, the WSL 2 session terminates “silently.” Note that there are no “exit” or “logout” messages in the screenshot above.
– After the conversion is complete, a Windows program (with no “admin” privileges) modifies the contents of the passwd program (changing the string “unchanged” to “1337 1337”).
Figure 9: conversion to WSL 1 / modifying passwd / Conversion back to WSL 2
– After the conversion back to WSL 2, passwd is still a SUID program, but it gives a different error message when the password is not modified (“password 1337 1337”).
Attack-D: The Loopback attack: Attack by a non-root program running inside WSL 2.
Being a “Lightweight Utility VM,” programs running inside WSL 2 can activate Windows programs (that will run under the Windows kernel).
This feature can be used by a standard program running inside WSL to take over the virtual Linux machine.
For this attack, we assume:
– A malicious program is running in a standard process in a currently active WSL VM.
The attack consists of the following steps:
a) A malicious non-root program running inside the WSL 2 machine:
- Creates a <malicious A>.exe and a <malicious B>.exe files in a Windows folder.
- Activates <malicious A>.exe (e.g. by “execve” command).
b) <malicious A>.exe program creates a detached process running <malicious B>.exe and terminates.
c) <malicious B>.exe executes Attack-C described above.
POC-D: A non-root program inside WSL 2 can modify any file in the WSL file system by going outside
Figure 10: In WSL 2- Show original sshd_config data/run a malicious non-root attack program
Figure 11:The batch command (attacking WSL) that we want to execute In Windows
We need to dissociate between the program activated from inside WSL 2 and the Windows attack since the attempt to convert into WSL 1 will immediately terminate the WSL 2 session (including the original “attack” Windows process). I achieved this through basic KB automation commands, which put the full path to the batch file in the Windows “Run-window” and then activated it.
Figure 12: Convert to WSL 1 / Modify the OpenSSH server configuration file / Convert to WSL 2
Note that the Windows program ReplaceStringInFile replaces the string “#PermitRootLogin” by the string “PermitRootLogin ”.
Figure 13: Back in WSL 2, the “protected” configuration file was modified as expected
WSL Insecurity Compared with Windows or Linux Standalone Implementation
By now, it should be clear why running sensitive applications inside WSL is significantly less secure than running the equivalent applications in a standalone Windows or Linux Desktop system, but let me spell it out anyway.
The Protection codes in the following table have the following meanings:
Ѵ: Access requires “admin” or “root” privileges.
–: Protection is not required
X: Access does not require “admin” or “root” privileges.
Each Entry is formatted like this:
R: < Protection code>
W: < Protection code>
(where ‘R’ stands for “Read Access” and ‘W’ stands for “Write Access”)
|OS files||Sensitive programs||Sensitive data files (e.g., SSH keys)||Sensitive configuration files|
|Windows||R: – W: Ѵ||R: – W: Ѵ||R: Ѵ W: Ѵ||R: – W: Ѵ|
|Linux||R: – W: Ѵ||R: – W: Ѵ||R: Ѵ W: Ѵ||R: – W: Ѵ|
|WSL (access from Windows, accessing files in WSL File System)||R: – W: X||R: – W: X||R: X W: X||R: – W: X|
An additional consideration is the security programs that may be active in the machine. To the best of my knowledge and at the time this blog was published, there is currently no known Windows security program that protects Linux files (inside the WSL file system).
Any security programs that might be implemented inside the WSL VM (e.g., maybe protecting SSH keys) will not be active while the attack is carried out.
The main security risk identified here is credentials theft or theft of other sensitive data processed by Linux applications running inside WSL. One could, quite reasonably, argue that there is no real security vulnerability here since the user should know that data inside a VM is always exposed to standard programs running in the “hosting” session.
But in this case the risk is more severe than the “normal” risk involved in running a VM under Windows because of the intended usage of WSL as a standard utility of Windows. One can infer this intended usage from Microsoft’s definition of WSL 2 as a “Lightweight Utility VM”. As discussed in the introductory section, the average WSL user will become less technically savvy and usage of WSL will increase as WSL will be used for more and more modern use-cases.
There is, however, a more critical and distinct security difference between running a full VM under Windows and running a WSL 2 VM. The loopback attack, for the WSL 2 VM, is a Local Privilege Escalation vulnerability that is explicitly enabled by the “Lightweight Utility VM” features of WSL 2. This vulnerability does not exist if an equivalent Linux system is run in a full VM under Windows.
Which brings me back to the title of this blog: (SAFE + SAFE) < SAFE.
WSL combines two secure (“safe”) systems in such a way that a less secure overall system is created.
Note: I would like to thank Gilad Reti for drawing my attention to the possibility of running a Windows program from inside the WSL VM and to this Microsoft presentation.