1. 项目概述从“计划任务”到权限提升的攻防博弈在Windows渗透测试与安全评估的实战中权限提升Local Privilege Escalation, LPE始终是攻防双方交锋的核心战场。我们常常会遇到这样的场景通过某种方式获得了一个普通用户权限的Shell但目标系统上存在关键数据或需要进一步横向移动此时一个有效的本地提权漏洞就是打开下一扇门的钥匙。在众多提权路径中Windows计划任务Task Scheduler因其设计复杂、配置灵活且普遍存在成为了一个极具价值的攻击面。这个“LPE Workshop”项目正是要深入Windows计划任务的肌理系统性地拆解其安全模型手把手地带你挖掘并利用其中潜藏的提权漏洞。这不仅仅是一个工具的使用教程更是一次对Windows安全机制底层逻辑的深度探索。对于安全研究人员、红队队员乃至系统管理员而言理解计划任务漏洞的成因与利用方式都至关重要。攻击者可以借此将低权限账户提升至SYSTEM或管理员权限而防御者则需要知道如何排查和加固。我们将从计划任务的基础架构讲起逐步深入到权限模型、触发器机制、动作配置等细节并辅以多个真实的漏洞案例如CVE-2019-1069、CVE-2020-0787等进行原理复现与利用演示。整个过程我会结合我过去在内部渗透测试中遇到的实际案例和踩过的坑确保你不仅能看懂更能亲手复现真正掌握这项关键的实战技能。2. Windows计划任务安全架构深度拆解要挖掘漏洞首先必须理解目标。Windows计划任务服务Schedule是一个功能强大的后台任务执行框架远比我们平时在图形界面里创建个“定时关机”任务要复杂得多。2.1 核心组件与数据流计划任务的核心是一个基于XML的存储和配置系统。每个任务本质上是一个.xml文件在Windows Vista及之后系统它们默认存储在C:\Windows\System32\Tasks目录及其子目录下。这些XML文件定义了任务的完整属性。另一个关键组件是任务计划程序库Task Scheduler Library它提供了管理和枚举这些任务的接口。任务的生命周期由几个关键环节构成定义与存储任务通过COM接口ITaskService或命令行工具schtasks.exe创建其配置被序列化为XML文件并存储。注册与触发任务创建后会向任务计划服务注册。触发器Trigger是任务启动的“开关”可以是时间、登录、系统启动等事件。执行与上下文当触发器条件满足时任务计划服务会启动任务中定义的动作Action通常是运行一个程序或脚本。这里最关键的是任务运行的安全上下文即任务以哪个用户的权限执行。理解这个数据流是漏洞挖掘的基础。攻击者关注的焦点在于如何影响一个高权限任务的定义、注册或执行过程从而让一个低权限上下文能够触发高权限代码的执行。2.2 权限模型与攻击面分析计划任务的权限模型是漏洞产生的温床主要涉及以下几个层面文件系统权限DACL任务XML文件本身是存储在文件系统上的NTFS文件。如果低权限用户对这些文件或其父目录拥有过高的权限如Write、Modify、Full Control就可能直接篡改任务内容。这是最经典的一类漏洞例如对C:\Windows\System32\Tasks或其子目录的错误权限配置。任务对象权限除了文件任务本身作为一个COM对象也有一套独立的安全描述符SD。可以通过icacls或PowerShell的Get-Acl/Set-Acl来查看和修改。如果低权限用户被授予了WriteDac或WriteOwner等权限就可以修改任务的安全属性进而控制任务。注册表权限任务的一些配置信息也存储在注册表中路径如HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache。对此注册表路径的错误权限设置同样可能导致漏洞。符号链接与路径解析任务中定义的动作如可执行程序路径或工作目录如果使用了环境变量或可由低权限用户控制的路径就可能存在符号链接攻击Symlink Attack或DLL劫持的风险。攻击者可以创建一个指向高权限位置的符号链接或者放置一个恶意的DLL诱导高权限任务加载。实操心得在实战中不要只盯着System32\Tasks目录。许多第三方软件如备份软件、监控代理安装的任务可能存放在自定义路径如C:\ProgramData\SomeVendor\Tasks这些路径的权限配置往往更加松懈是绝佳的突破口。我曾在一个项目中通过一个第三方日志收集软件的任务目录的弱权限成功实现了提权。3. 漏洞挖掘方法论从信息收集到漏洞定位有了理论框架我们进入实战环节。漏洞挖掘是一个系统性的过程不能盲目乱撞。3.1 全面的信息收集首先我们需要全面枚举目标系统上的所有计划任务。图形界面的taskschd.msc不够灵活我们主要依靠命令行。使用schtasks命令这是最基础的工具。schtasks /query /fo LIST /v可以列出所有任务的详细信息包括任务路径、下次运行时间、运行状态以及运行为的用户账户。重点关注“运行为”是SYSTEM、Administrator或其它高权限账户的任务。使用PowerShellPowerShell提供了更强大的对象化操作能力。# 获取所有任务 Get-ScheduledTask | Select-Object TaskName, TaskPath, State, {NamePrincipal;Expression{$_.Principal.UserId}} # 获取指定任务的详细信息包括触发器和动作 Get-ScheduledTask -TaskName HighPrivTask | Get-ScheduledTaskInfo $task Get-ScheduledTask -TaskName HighPrivTask $task.Actions # 查看动作 $task.Triggers # 查看触发器 $task.Principal # 查看运行主体用户手动检查文件系统直接浏览C:\Windows\System32\Tasks目录及其子目录查看所有.xml文件。对于非系统任务记得检查C:\ProgramData、用户AppData目录等。3.2 权限分析与脆弱点识别收集到任务列表后下一步是分析每个高权限任务的“可攻击性”。检查任务XML文件权限# 使用icacls检查具体文件的权限 icacls C:\Windows\System32\Tasks\Microsoft\Windows\Defrag\ScheduledDefrag # 使用PowerShell获取并解析ACL $acl Get-Acl -Path C:\Windows\System32\Tasks\SomeTask $acl.Access | Format-Table IdentityReference, FileSystemRights, AccessControlType, IsInherited -AutoSize你需要寻找任何授予了BUILTIN\Users、Authenticated Users或当前低权限用户Write、Modify、FullControl权限的条目。特别要注意“拒绝”权限Deny是否优先于“允许”权限。检查任务目录权限如果单个文件权限严格但其父目录权限宽松你或许可以在该目录下创建新的任务文件。检查目录的权限icacls C:\Windows\System32\Tasks\ThirdParty如果目录有WriteData / AddFile权限就可能实现“任务植入”。分析任务内容打开任务的XML文件需要管理员权限或相应文件读取权重点关注Actions节点执行的命令是什么路径是否使用了环境变量如%windir%、%programfiles%是否指向一个可写的目录Principals节点确认运行用户UserId。Triggers节点任务何时触发是否有登录时触发LogonTrigger的任务这类任务在用户登录时运行可能被用来实现持久化。Settings节点是否允许AllowHardTerminate或MultipleInstances等属性这些可能影响利用的稳定性。检查注册表权限对于某些顽固的任务可以检查其注册表项权限。# 首先找到任务的GUID # 可以通过任务XML中的RegistrationInfo\URI字段或遍历注册表匹配任务名 # 然后检查该GUID对应注册表项的权限 $regPath HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\YourTaskName Get-Acl -Path $regPath | Select -ExpandProperty Access3.3 利用PowerUp进行自动化侦察手动检查虽然彻底但效率较低。在渗透测试中我们常使用自动化工具进行初筛。PowerShell框架PowerUp中的Get-ModifiableScheduledTaskFile函数就是这样一个利器。它会自动遍历计划任务检查当前用户是否有权限修改任务文件或相关的可执行文件。# 导入PowerUp.ps1后 Get-ModifiableScheduledTaskFile | Select-Object TaskName, TaskFilePath, ModifiableFile这个命令能快速列出所有可能被篡改的任务极大提升效率。但切记自动化工具可能存在误报或漏报关键漏洞仍需手动验证。4. 经典漏洞模式与利用实战解析理论结合实践我们来看几个具体的漏洞模式和利用手法。4.1 模式一可写任务XML文件CVE-2019-1069类似这是最直接的漏洞模式。假设我们发现一个以SYSTEM权限运行的任务\Microsoft\Windows\DiskCleanup\SilentCleanup其XML文件路径为C:\Windows\System32\Tasks\Microsoft\Windows\DiskCleanup\SilentCleanup并且Users组对该文件有Modify权限。利用步骤备份原任务首先备份原始XML文件以便后续恢复。copy C:\Windows\System32\Tasks\Microsoft\Windows\DiskCleanup\SilentCleanup C:\temp\SilentCleanup.bak分析原任务查看原任务内容了解其触发条件。例如它可能是一个事件触发器EventTrigger。我们需要确保我们的恶意任务能在合适的时机被触发或者直接修改触发器为立即执行或登录时执行。构造恶意任务XML我们不需要从头编写可以修改原文件。关键修改点在Actions节点。将其中的Exec命令改为我们想要执行的命令例如启动一个反向Shell或添加一个管理员用户。!-- 原始动作可能类似 -- Actions ContextAuthor Exec Commandcleanmgr.exe/Command /Exec /Actions !-- 修改为 -- Actions ContextAuthor Exec !-- 例如添加一个管理员用户 -- Commandcmd.exe/Command Arguments/c net user hacker Pssw0rd! /add net localgroup administrators hacker /add/Arguments /Exec /Actions同时为了立即生效可以修改或添加一个触发器。例如添加一个TimeTrigger将开始时间设为当前时间的一分钟后。Triggers TimeTrigger StartBoundary2023-10-27T14:30:00/StartBoundary !-- 设置为未来1分钟 -- Enabledtrue/Enabled /TimeTrigger /Triggers覆盖原文件将修改后的XML内容写回原路径。# 注意可能需要先取消文件的只读属性 attrib -r C:\Windows\System32\Tasks\Microsoft\Windows\DiskCleanup\SilentCleanup # 然后使用echo或copy覆盖这里建议使用PowerShell或编程方式写入更可靠等待触发或手动触发等待任务计划服务读取修改后的文件并执行。对于某些任务可以尝试手动触发例如通过schtasks /run /tn \Microsoft\Windows\DiskCleanup\SilentCleanup。但注意手动触发可能受到权限限制最好依赖其原有的自动触发机制。踩坑记录直接覆盖XML文件时任务计划服务可能因为缓存原因不会立即重新加载任务定义。一个更可靠的方法是先schtasks /delete删除任务再schtasks /create用我们的XML文件创建同名任务。但删除任务通常需要更高权限。因此在仅能修改文件的情况下重启计划任务服务net stop schedule / net start schedule或重启系统是强制重新加载的有效方法但这在渗透测试中可能不现实。更好的方法是利用任务本身的触发频率比如一个每分钟运行一次的任务我们修改后只需等待一分钟。4.2 模式二可写任务目录与任务植入如果无法修改现有高权限任务但对其所在目录有写权限我们可以尝试“植入”一个全新的任务。寻找可写目录例如发现C:\Windows\System32\Tasks\Microsoft\Windows\AppID目录对Users组可写。创建恶意任务XML在本地创建一个完整的任务XML文件。可以利用schtasks /create /xml template.xml /tn temp命令创建一个临时任务然后将其XML文件导出作为模板修改这样能保证XML结构正确。重点设置Principals: 将UserId设置为SYSTEM或高权限账户。Actions: 设置要执行的恶意命令。Triggers: 设置为一个很快会触发的时间或者LogonTrigger用户登录时触发。Settings: 将AllowHardTerminate设为falseHidden设为true可能有助于隐蔽。植入文件将制作好的XML文件复制到可写目录下文件名即为任务名例如C:\Windows\System32\Tasks\Microsoft\Windows\AppID\OurBackdoor。注册任务仅仅放置文件可能不够需要让任务计划服务“知道”它。可以尝试使用schtasks /query强制刷新或者等待系统某种事件触发服务扫描目录。更主动的方法是调用COM接口但这通常需要一定权限。在实践中放置文件后重启服务、系统或等待相关事件如用户重新登录是常见的触发方式。4.3 模式三路径劫持与DLL注入如果任务执行的是一个来自可写路径的程序或者其工作目录可写就可能存在路径劫持。识别脆弱路径任务动作中的Command可能是C:\Program Files\Vendor\Tool.exe。检查C:\Program Files\Vendor目录的权限。或者命令中使用了非绝对路径系统会在%PATH%环境变量列出的目录中查找而%PATH%中可能包含可写目录如当前用户目录。DLL劫持DLL Hijacking如果目标程序存在DLL劫持漏洞即它会尝试从当前目录等不安全位置加载DLL我们可以将恶意DLL放置在可写的工作目录或程序同级目录下。需要逆向分析或测试确定程序加载哪些DLL。可执行文件替换如果对程序文件本身有写权限那是最直接的。但通常权限很严格。更常见的是对程序所在目录的父目录有“创建子目录/文件”的权限但无法覆盖现有文件。此时可以尝试利用Windows文件解析特性如tool.exe.local目录、.exe与.dll的加载顺序等但现代Windows版本已加强防护。符号链接攻击Symlink Attack这是更高级的技巧。如果任务以高权限运行且其执行路径或参数的一部分指向一个我们可以控制的路径如C:\temp\input.log我们可以删除这个文件并创建一个指向敏感系统文件如C:\Windows\System32\cmd.exe的符号链接需要SeCreateSymbolicLinkPrivilege普通用户默认没有或硬链接普通用户可能有权创建。但任务在读取或写入该文件时就可能对系统文件进行操作。这种利用条件较为苛刻。5. 实战案例复现CVE-2020-0787Windows 后台智能传输服务提权让我们以一个近年的真实漏洞CVE-2020-0787为例完整走一遍挖掘和利用流程。该漏洞存在于Windows后台智能传输服务BITS中与计划任务紧密相关。漏洞原理简述BITS服务允许用户创建下载或上传作业。其中有一个功能可以创建一个计划任务来在特定时间运行作业。在创建这个任务时服务会设置任务XML文件的安全描述符。漏洞在于低权限用户能够修改该任务的安全描述符从而获得对任务的完全控制权进而可以修改任务内容实现以SYSTEM权限执行任意代码。复现环境Windows 10 1909 (未打2020年3月补丁)。利用步骤信息收集首先我们知道BITS与计划任务交互。我们可以检查BITS相关的任务。Get-ScheduledTask -TaskName *BITS* | Select TaskName, State, Principal可能会发现一个名为\Microsoft\Windows\BITS\BITSClient的任务。权限检查使用PowerUp或手动检查该任务文件的权限。Get-ModifiableScheduledTaskFile | ? {$_.TaskName -like *BITS*}在存在漏洞的系统上这个命令会返回该任务文件可被当前用户修改。利用脚本由于利用过程涉及与BITS服务COM接口的复杂交互手动操作繁琐。安全研究人员已经开发了成熟的利用脚本例如用C#或PowerShell编写的Exp。我们以一款公开的PowerShell脚本为例假设为Invoke-CVE-2020-0787.ps1。# 导入利用脚本 . .\Invoke-CVE-2020-0787.ps1 # 执行利用该脚本内部会 # a. 创建一个恶意的BITS作业。 # b. 利用漏洞修改关联计划任务的安全描述符。 # c. 将任务的动作改为执行我们的Payload如添加用户、反弹Shell。 # d. 触发任务执行。 Invoke-CVE-2020-0787 -Command cmd /c net user expuser ExpPass123! /add net localgroup administrators expuser /add验证结果执行成功后检查管理员组是否增加了新用户。net localgroup administrators漏洞分析这个漏洞的精妙之处在于它并非简单的文件权限配置错误而是服务逻辑漏洞。BITS服务在创建任务时错误地允许低权限用户设置任务对象的安全描述符绕过了本应有的权限检查。这提醒我们漏洞挖掘不仅要看静态配置还要分析服务间的动态交互和逻辑缺陷。6. 防御、检测与排查指南作为防守方了解攻击手法后如何构建防线6.1 安全加固建议最小权限原则定期审计C:\Windows\System32\Tasks及其子目录、C:\ProgramData下所有任务目录的NTFS权限。确保只有SYSTEM、TrustedInstaller和必要的管理员账户有写权限。移除Authenticated Users或Users组的写权限。对于第三方软件安装的任务将其迁移到受控的、权限严格的目录或联系厂商获取安全配置指南。任务配置审查审查所有以高权限尤其是SYSTEM运行的任务。问自己这个任务是否必须高权限能否以更低权限运行检查任务动作中的命令行参数避免使用环境变量指向用户可写路径尽量使用绝对路径。禁用不必要的任务。启用Windows Defender攻击面减少规则如果环境允许可以启用“阻止从Windows本地安全机构子系统窃取凭据”等相关规则这能阻断一些利用技术。应用最新补丁及时安装系统更新修复如CVE-2020-0787这类已公开的服务逻辑漏洞。6.2 入侵检测与应急响应监控关键文件变更使用Sysmon或Windows审计策略监控对C:\Windows\System32\Tasks目录下XML文件的创建、修改和删除事件。Sysmon的Event ID 11文件创建和Event ID 2文件流创建非常有用。!-- Sysmon 配置示例监控Tasks目录 -- FileCreate onmatchinclude TargetFilename conditioncontainsC:\Windows\System32\Tasks/TargetFilename /FileCreate监控计划任务事件Windows安全日志中Event ID 4698计划任务创建和4699计划任务删除记录了任务的创建和删除行为。Event ID 4702计划任务更新记录任务的修改。集中收集并分析这些日志特别是关注由非管理员账户发起这些操作的事件。基线比对在安全状态下导出所有计划任务的列表和其XML文件的哈希值。定期进行比对可以发现异常的任务新增或篡改。# 导出所有任务信息 Get-ScheduledTask | Export-Clixml -Path C:\baseline\ScheduledTasks.xml # 计算所有任务文件的哈希 Get-ChildItem C:\Windows\System32\Tasks -Recurse -Filter *.xml | Get-FileHash | Export-Csv C:\baseline\TaskHashes.csv应急响应排查当怀疑系统被入侵时立即检查最近创建或修改的计划任务按创建/修改时间排序。所有以高权限运行的任务尤其是动作可疑的如执行cmd /c、powershell -enc等。检查任务历史记录在任务属性中看是否有异常的执行记录。6.3 高级狩猎查询示例对于使用Microsoft 365 Defender或Azure Sentinel的安全团队可以编写高级狩猎查询KQL来寻找可疑的计划任务活动DeviceProcessEvents | where InitiatingProcessFileName ~ schtasks.exe or InitiatingProcessFileName ~ powershell.exe | where ProcessCommandLine has_all (create, task) or ProcessCommandLine has_all (schtasks, /create) | where AccountName !in (SYSTEM, Administrator, YOUR_ADMIN_ACCOUNT) // 过滤非管理员操作 | project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, ProcessCommandLine这个查询可以抓取非管理员账户创建计划任务的进程执行事件。7. 工具链与自动化审计脚本工欲善其事必先利其器。除了前文提到的PowerUp还有一些优秀的工具和脚本可以集成到你的审计流程中。WinPEAS这是一款功能强大的Windows本地提权枚举脚本。它的winpeas.exe quiet模式会快速检查计划任务中的权限问题输出非常直观。AccessChk (Sysinternals Suite)虽然老牌但依然强大。可以快速检查文件、目录、注册表键、服务等的权限。accesschk.exe -wusd C:\Windows\System32\Tasks -accepteulaJAWS (Just Another Windows (Enum) Script)一个PowerShell枚举脚本其中包含了对计划任务的检查模块。自定义PowerShell审计脚本你可以编写自己的脚本实现更定制化的检查。例如一个脚本可以遍历所有任务检查其运行用户、触发器类型并自动对其XML文件路径进行权限检查最后生成一份风险报告。# 简易示例框架 $tasks Get-ScheduledTask foreach ($task in $tasks) { $taskPath $task.TaskPath $task.TaskName $xmlPath C:\Windows\System32\Tasks $taskPath.Replace(\, \) .xml if (Test-Path $xmlPath) { $acl Get-Acl -Path $xmlPath $access $acl.Access | Where-Object {$_.IdentityReference -eq BUILTIN\Users -and $_.FileSystemRights -match Write|Modify|FullControl} if ($access) { Write-Host [!] Vulnerable Task Found: $taskPath -ForegroundColor Red Write-Host Running as: $($task.Principal.UserId) -ForegroundColor Yellow Write-Host Modifiable by: $($access.IdentityReference) -ForegroundColor Yellow } } }将这些工具和脚本纳入你的标准化渗透测试或安全审计流程能系统性地发现计划任务层面的安全风险。8. 绕过与对抗当常规利用遇到障碍在实战中你可能会遇到一些防护措施需要更巧妙的绕过技术。受保护的TasksWindows有一些“受保护的任务”其XML文件存储在C:\Windows\Tasks旧格式或受TrustedInstaller保护常规方法无法修改。对于这些需要寻找其他逻辑漏洞如前面提到的CVE-2020-0787或结合其他提权链。文件完整性监控如果目标系统有FIM文件完整性监控直接修改系统目录下的XML文件可能会触发告警。此时可以考虑内存操作尝试不修改磁盘文件而是通过API在内存中篡改任务属性。这需要更深入的逆向工程和利用开发能力。利用可写目录植入如前所述在可写目录创建新任务避免触碰受监控的系统文件。Living-off-the-land利用系统合法的、高权限的任务通过修改其参数或依赖项如脚本、配置文件来执行代码这些文件可能不在严格的监控范围内。杀软拦截你的恶意命令如net user、powershell -enc可能会被终端杀毒软件拦截。需要混淆命令或使用无文件技术。代码执行混淆使用certutil -decode、msiexec、rundll32等合法白程序加载Payload。修改任务动作不直接执行cmd.exe而是执行一个看似合法的程序如notepad.exe但通过DLL劫持或COM劫持通过修改注册表InprocServer32让该程序加载我们的恶意DLL。这需要更前置的准备工作。权限提升后的清理成功提权后记得清理你创建或修改的任务抹除痕迹。但要注意删除行为本身也可能被日志记录。计划任务的攻防是一场持续的猫鼠游戏。作为攻击方需要不断深入理解Windows内部机制寻找新的薄弱环节作为防御方则需要建立纵深防御体系从权限配置、行为监控到漏洞补丁管理多管齐下。通过这个“LPE Workshop”的深度旅程希望你已经不仅掌握了几个漏洞利用的命令更构建起了围绕Windows计划任务进行安全审计和渗透测试的完整方法论框架。真正的安全能力源于对系统深入骨髓的理解和永不停歇的实战锤炼。