In this post, I’ll discuss an arbitrary file move vulnerability I found in Windows Service Tracing. From my testing, it affected all versions of Windows from Vista to 10 but it’s probably even older because this feature was already present in XP.

TL;DR

Service Tracing is an old feature that I could trace back to Windows XP but it probably already existed in previous versions of the OS. It aims at providing some basic debug information about running services and modules. It can be configured by any local user, simply by editing some registry keys and values under HKLM\SOFTWARE\Microsoft\Tracing .

A service or module is associated to a registry key. Each key contains 6 values (i.e. settings). The 3 values we will focus on are: EnableFileTracing (enable / disable the “tracing”), FileDirectory (set the location of the output log file) and MaxFileSize (set the maximum file size of the log file).

Once EnableFileTracing is enabled, the target service will start writing to its log file in the directory of your choice. As soon as the size of the output file exceeds MaxFileSize , it will be moved (the .LOG extension is replaced by .OLD ) and a new log file will be created.

Thanks to James Forshaw’s symbolic link testing tools, the exploit is quite simple. All you need to do is set the target directory as a mountpoint to the \RPC Control object directory and then create two symbolic links:

A symbolic link from MODULE.LOG to a file you own (its size must be greater than MaxFileSize ).

to a file you own (its size must be greater than ). A symbolic link from MODULE.OLD to any file on the file system (e.g.: C:\Windows\System32\WindowsCoreDeviceInfo.dll ).

Finally, the file move can be triggered by targeting a service running as NT AUTHORITY\SYSTEM and, the Update Session Orchestrator service can then be leveraged to get arbitrary code execution.

The Tracing Feature for Services

As briefly mentioned before, the Service Tracing feature can be configured by any local user, simply by editing some registry keys and values under HKLM\SOFTWARE\Microsoft\Tracing .

Using AccessChk from the Windows Sysinternals tools suite, we can see that regular Users have Read / Write permissions on almost all the sub-keys.

For the rest of this article, I’ll use the RASTAPI module as an example since it’s the one I leveraged in my exploit. This module is used by the IKEEXT service. Therefore, log events can be easily triggered by initiating dummy VPN connections. The following screenshot shows the default content of the registry key. The exact same values are configured for the other services and modules.

From a local attacker’s standpoint, here are the most interesting values:

Name Possible values Description EnableFileTracing 0 - 1 Start / Stop writing to the log file. FileDirectory A String The absolute path of a directory. MaxFileSize 0x00000000 - 0xffffffff The maximum size of the output log file.

By setting these values, we can:

Force a specific service or module to start or stop writing debug information to a log file by setting EnableFileTracing to either 0 or 1 .

debug information to a log file by setting to either or . Specify the location of the log file by setting FileDirectory .

of the log file by setting . Specify the maximum size of the output file by setting MaxFileSize .

The only caveat is that we cannot choose the name of the output file since it’s based on the name of the debugged service or module. This issue can be easily addressed using symbolic links though.

The Arbitrary File Move Vulnerability

With all the previous elements of context in mind, the vulnerability can be easily explained.

Case #1: MaxFileSize - Default value

For this first test case, I simply set C:\LOGS as the output directory and enabled the File Tracing.

Now, if we want the target service to start writing to this file, we must generate some events. A very simple way to do so is to initiate a dummy VPN connection using the rasdial command and a PBK file.

It worked! The log file was written by NT AUTHORITY\SYSTEM . Its size is now around 24KB.

Case #2: MaxFileSize - Custom value

In the previous test, we saw that the final size of the output log file was around 24KB. Therefore, this time, we will set MaxFileSize to 0x4000 (16,384 bytes) and restart the test.

The events captured by “Process Monitor” can be summarized as follows:

Basic information about the log file is fetched by the service. We can see that the EndOfFile is at offset 23,906, which is the size of the file at this moment. The problem is that we specified a max file size of 16,384 bytes so, the system will consider that there is no more free space. SetRenameInformationFile is called with FileName=C:\LOGS\RASTAPI.OLD . In other words, since the existing file is considered as full, it is moved from C:\LOGS\RASTAPI.LOG to C:\LOGS\RASTAPI.OLD . The service creates a new C:\LOGS\RASTAPI.LOG file and starts writing to it.

The “Move” operation is performed as NT AUTHORITY\SYSTEM . Therefore, it can be leveraged to move a user-owned file to any location on the file system, such as C:\Windows\System32\ .

The Exploit

The exploit is simple and can be summarized as follows:

Create (or copy) a file with a size greater than 0x8000 (32,768) bytes. Create a new directory ( C:\EXPLOIT\mountpoint\ for example) and set it as a mountpoint to \RPC Control . Create the following symbolic links: \RPC Control\RASTAPI.LOG -> \??\C:\EXPLOIT\FakeDll.dll (owner = current user) \RPC Control\RASTAPI.OLD -> \??\C:\Windows\System32\WindowsCoreDeviceInfo.dll Configure the following values in the registry: FileDirectory = C:\EXPLOIT\mountpoint MaxFileSize = 0x8000 (32,768‬ bytes) EnableFileTracing = 1 Trigger RASTAPI related events using the RasDial function from the Windows API. Trigger the Update Session Orchestrator service to load the DLL in the context of NT AUTHORITY\SYSTEM .

Demo