Untrusted search path in Windows Phone Task Scheduler
TL;DR
An elevation of privilege vulnerability exists when the Windows Phone Task Scheduler (WPTaskScheduler
) improperly handles loading of DLL
files potentially allowing low privileged users to execute arbitrary code in the context of the local SYSTEM
account, in case there is an unprotected folder among the PATH
directories of the local SYSTEM
account.
Description
The Task Scheduler
service enables a user to configure and schedule automated tasks on the computer. The service runs in the context of the local SYSTEM
account and it is auto-started during system boot to initialize the scheduled tasks. The initialization process also includes Scheduled Tasks for Windows Phone implemented in the WPTaskScheduler.dll
module and performed by the TsiInitialize()
function.
The TsiInitialize()
function will look for extensions implemented in the (by default) non-existent WptsExtensions.dll
module using the LoadLibraryW()
function without specifying an absolute path to the module. This method is known to be insecure to load DLL modules:
When no path is specified, the function searches for loaded modules whose base name matches the base name of the module to be loaded. If the name matches, the load succeeds. Otherwise, the function searches for the file.
The below is the relevant excerpt of the TsiInitialize()
functions’ pseudocode:
1g_hModuleWptsExtensions = LoadLibraryW(L"WptsExtensions.dll");
2if ( g_hModuleWptsExtensions )
3{
4 v24 = (struct _ActionExtFunctions *)operator new(0x28ui64, (const struct std::nothrow_t *)&std::nothrow);
5 ActionExtensionFunctionTable = v24;
6 if ( v24 )
7 {
8 memset((void *)v24, 0, 0x28ui64);
9 *(_QWORD *)ActionExtensionFunctionTable = GetProcAddress(g_hModuleWptsExtensions, "WptsCreateAction");
10 *((_QWORD *)ActionExtensionFunctionTable + 1) = GetProcAddress(g_hModuleWptsExtensions, "WptsDestroyAction");
11 *((_QWORD *)ActionExtensionFunctionTable + 2) = GetProcAddress(g_hModuleWptsExtensions, "WptsCopyActionData");
12 *((_QWORD *)ActionExtensionFunctionTable + 3) = GetProcAddress(g_hModuleWptsExtensions, "WptsFreeActionData");
13 *((_QWORD *)ActionExtensionFunctionTable + 4) = GetProcAddress(g_hModuleWptsExtensions, "WptsLaunchAction");
14 }
15}
The below screenshot shows that the Task Scheduler
service searches for the WPTaskScheduler.dll
module in the PATH
directories:
Exploitation
I have found some cases when a standard user’s %LOCALAPPDATA%\Microsoft\WindowsApps
directory is added to the PATH
directories of the local SYSTEM
account. This may allow to elevate privileges and execute code in the context of the local SYSTEM
account, because the WindowsApps
folder is writable without elevating permissions. According to MSRC the culprit was the .NET Core installer, however, this issue does not meet the bar for servicing. Anyway, it can be reproduced on a Windows 10 VM provided by Microsoft.
- Plant a malicious
WptsExtensions.dll
module in the%LOCALAPPDATA%\Microsoft\WindowsApps
directory. - Restart the virtual machine.
- The malicious code in the planted DLL module has been executed as
SYSTEM
.
PoC
Stefan Kanthak’s Vulnerability and Exploit Detector is a great tool for researching potential DLL planting vulnerabilities. When SENTINEL.DLL
runs in an interactive user session it displays one or more message boxes. When executed, it writes a message similar to that shown in the message boxes to the Event Log, using the source Vulnerability and Exploit Detector
. I have planted SENTINEL.DLL
file as WptsExtensions.dll
in the WindowsApps
folder and restarted the machine to confirm that the DLL module is indeed being loaded and executed by SYSTEM
as the below screenshot shows:
Timeline
⬅️ 2020-03-08: Reported issue to MSRC.
➡️ 2020-03-10: MSRC opened case 57121.
➡️ 2020-03-11: MSRC requested more information.
⬅️ 2020-03-11: Provided more information for MSRC to review.
➡️ 2020-03-12: MSRC indicated that this issue will not be fixed.