This post is also available in: 日本語 (Japanese)
In recent years, one of the most common classes of elevation-of-privilege vulnerabilities is file system redirection attacks. This class abuses the fact that a privileged component, such as a Windows service, operates on files or directories that are writable by unprivileged users. By using different types of file system links, such as hard links or junctions, attackers can trick the privileged component into operating on files it didn’t intend to. The end goal for such attacks is usually to write an attacker-supplied executable (such as a DLL or a script) to disk, and to get it executed with system permissions.
This piece explains junctions and how threat actors use them in file system redirection attacks, then explores a developing mitigation.
Palo Alto Networks customers receive protections from Cortex XDR against exploits for different types of file system redirection attacks.
Junctions are a feature of the NT file system (NTFS) that make it possible to link one directory into another. They are used by default, linking some directories such as C:\Documents and Settings.
In 2019, Microsoft introduced a mitigation that requires the creator of hard links to have write access to those links’ targets. Since then, junctions became the way to go for attackers when exploiting file system redirection attacks.
A common vulnerable pattern is usually as follows:
- A privileged service exposes functionality that can be triggered through some interprocess communication (IPC) mechanism, such as remote procedure call (RPC). That functionality can be triggered by users running at lower privilege levels.
- That functionality operates on a file (e.g. writing data into that file) that is located under a globally writable directory. The operation is done without impersonation, meaning it occurs with the permissions of that system service.
To exploit such bugs, the attacker first creates a junction between that directory and their target, which is usually C:\Windows or one of its subdirectories. Next, the attacker triggers the RPC call, which follows the junction to overwrite a system DLL file. Finally, that malicious DLL is loaded by some service, and the attacker’s supplied code gets executed with system permissions.
Microsoft announced they are going to ship a mitigation for this bug class in David Weston’s talk at BlueHat IL 2020 – “Keeping Windows Secure.” However, this mitigation only appeared on recent Windows 10 builds, so I decided to reverse engineer it and explore how it works.
The mitigation is fairly simple and follows the guidelines presented at Microsoft’s BlueHat talk. Its goal is to mark junctions created by unprivileged, medium-integrity actors, and prevent privileged processes from following them.
Every time a junction is created, ntfs.sys calls nt!IoComputeRedirectionTrustLevel to compute the caller’s trust level. The level is determined based on the caller’s token – either the impersonation token (if present) or the primary token. Later, it sets that value into that junction file control block’s standard information.
Currently, there are only two trust levels:
- Level 1 – Indicating the junction was created by a medium-integrity actor.
- Level 2 – Indicating the junction was created by a privileged actor (administrator, system or kernel).
To complete the mitigation, the trust level is verified before following junctions. This is done only if the mitigation is enabled, which is controlled by a new process mitigation policy – ProcessRedirectionTrustPolicy. That policy has two modes: audit or enforce.
When SetProcessMitigationPolicy is called with the relevant arguments, it ends up calling nt!PspSetRedirectionTrustPolicy. This enables the mitigation on the process’s primary token.
Finally, when ntfs.sys goes through a junction redirection, it verifies it against the caller’s token using nt!IoCheckRedirectionTrustLevel. This means that when a privileged service operates with its own system privileges, untrusted junctions are not followed. Failed redirects end up with error 0xc00004be – “The path cannot be traversed because it contains an untrusted mount point.”
After reverse engineering the mitigation, I wanted to check whether it is enabled on the current Windows build, and in which mode. I created a sample app that queries the state of all running processes (using GetProcessMitigationPolicy), and found out that the mitigation is currently only enabled in audit mode for several services. Hopefully, in the near future, Microsoft will enable it in enforce mode.
In the last few years, Microsoft has pushed numerous mitigations to address file system redirection attacks. It is important to explore them and assess their effectiveness, trying to identify gaps and conditions where bugs can still be exploitable.
Palo Alto Networks Cortex XDR already has many protections in place to prevent exploits for different types of file system redirection attacks, and was proven to prevent such attacks in the wild.