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.
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
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).
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
- A symbolic link from
MODULE.OLD to any file on the file system (e.g.:
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
AccessChk from the Windows Sysinternals tools suite, we can see that regular
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:
||0 - 1
||Start / Stop writing to the log file.
||The absolute path of a directory.
||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
- Specify the location of the log file by setting
- Specify the maximum size of the output file by setting
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
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
- 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
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
- 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
Links & Resources