聊到Windows系统的攻击方式,本地提权是绕不开的一环。大多数安全事件里,攻击者最初拿到的权限并不高,可能只是一个Web应用池账户、一个普通域账号,真正让防守方头疼的往往是后续的提权动作。一旦本地提权成功,低权限进程直接变成SYSTEM,后面读取密码哈希、关闭防护软件、横向移动都成了顺理成章的事。这篇文章想从一个偏防守的视角,把Windows本地提权常见的思路、原理和对应的加固手段拆开讲清楚。适合刚入门的安全运维、系统管理员,以及正在写检测规则的蓝队同学。
1. 本地提权到底是什么:先搞清楚敌我边界
1.1 权限边界与常见误解
本地提权(Local Privilege Escalation)听起来像是“获取最高权限”这一件事,但严格来说,它描述的是攻击者已经拿到一台Windows主机上的本地执行权限之后,再利用系统自身的缺陷或错误配置,把当前进程的权限从普通用户提升到管理员甚至SYSTEM的过程。
很多人把提权和“破解密码”混为一谈,这是个常见误解。提权的前置条件不是知道管理员密码,而是已经能在目标机器上执行命令。举一个常见场景:攻击者通过网站上传漏洞拿到一个webshell,此时命令执行身份可能是IIS的应用池账户,连读取另一个用户目录的权限都没有,更别提操作系统底层功能。接下来他做的第一步往往不是横向移动,而是先在当前机器上寻找提权机会。如果提权失败,他连继续探测内网的资格都没有。
理解Windows的权限模型,可以先抓住三个关键词:访问令牌、用户权限、完整性级别。每次进程启动时,Windows会为该进程生成一个访问令牌,令牌里写着这个进程属于哪个用户、属于哪些组、拥有哪些特权。表面上你以自己的名义登录,实际系统判断权限时看的全是令牌内容。本地提权的本质,就是让一个本来只有低权限令牌的进程,获得一个包含更多特权和高完整性级别的令牌。
还有一个容易被忽略的点:即便你的账户属于本地管理员组,日常运行程序时,Windows也会在UAC机制下给进程分配一个受限令牌。只有当程序申请提升并以管理员身份运行时,系统才会切换到完整管理员令牌。这意味着“在管理员组里”和“能以管理员权限执行命令”并不能画等号。理解了这一点,后续再看服务配置、计划任务、令牌模拟这些具体路径,就会清楚为什么它们会成为提权突破口。
1.2 本地提权的典型触发场景
本地提权不是凭空发生的,它一定有一个“低权限起点”。我处理过的大多数实战案例里,攻击者进入低权限状态的路径无非这么几种:
- Web漏洞利用:网站存在文件上传、命令注入、反序列化等问题,攻击者成功执行系统命令,进程身份是Web应用池账户。
- 钓鱼与横向移动:攻击者通过钓鱼邮件或口令复用,拿到了一个普通域账户,该账户能登录某些业务服务器,但没有管理员权限。
- 物理接触:攻击者能够暂时接触一台无人值守的电脑,却只有标准用户登录界面。
- 供应链或第三方软件投递:某个低权限恶意进程已经运行,但被防护软件拦截,无法做管理员操作,于是尝试利用系统错误配置提权。
这些场景有一个共同特征:攻击者在目标机器上的“物理层”和“用户层”已经失守,操作系统成了最后一道防线。所以防守方不能只防外部边界,还必须假设“内网主机已经被突破”来设计检测和加固策略。本地提权检测因此变得异常重要——它不是最前线,却是失守之后能否兜底的关键。
2. 常见的本地提权思路与分类
2.1 内核漏洞类提权
Windows内核提权是最经典的一类。它的原理不复杂:操作系统内核运行在最高权限级别,应用程序通过系统调用进入内核时,如果内核代码存在越界写、类型混淆或释放后使用这类漏洞,低权限进程就可以利用它篡改内核数据,最终在当前进程上注入一段以SYSTEM权限执行的代码。不需要服务配置错误,也不需要额外账户权限,只要系统没打补丁,攻击者拿着一个公开漏洞就能完成提权。
这也是为什么补丁管理永远是提权防御的第一项。对内网Windows机器来说,安装安全更新的作用不只是修bug,而是把攻击者常用的内核漏洞利用路径直接堵死。实际操作中,我见过不少企业给服务器积极打补丁,却把几百台工作站的自动更新关掉了。攻击者恰恰更愿意从工作站下手,因为工作站在人员密集、应用复杂、补丁滞后的环境里更容易出问题。一次钓鱼邮件在某个员工电脑上落地,接着利用未修补的内核漏洞提到SYSTEM,再横向走一圈,影响范围会迅速扩大。
需要特别提醒的是,不要以为打了补丁就万事大吉。新型漏洞被公开到补丁发布之间,存在一个“利用窗口期”;即便微软发布补丁,内网资产太多,也没法在一个晚上全部更新。所以在补丁覆盖率还没达到理想水平时,必须搭配应用白名单、攻击面缩减和日志审计,尽量让漏洞利用的第一步无法执行。
2.2 服务与计划任务滥用
这部分是实战中我见过最频繁的提权路线,也是被大量漏掉的一类。Windows服务本来设计成以高权限身份在后台运行,系统服务大多以SYSTEM账户启动,第三方服务也经常配置成管理员或SYSTEM权限。问题出在“谁能管理服务”以及“服务实际启动的是什么程序”上。
第一种典型问题:低权限用户对某个服务拥有写配置的权限。Windows服务在注册表和服务数据库中的安全描述符,决定了谁能修改服务的二进制路径、启动参数和启动账户。如果运维图省事,把某个服务的权限设置成Everyone可写,或者用不太严谨的工具修改过服务安全标识,普通用户就能把服务指向自己上传的恶意程序。等攻击者启动服务,恶意程序便以SYSTEM身份运行。
第二种典型问题:服务二进制路径里的可写目录。以前经常出现“服务路径未加引号”的利用方式:路径写成C:\Program Files\某软件\update.exe,系统解析时会按空格分隔尝试多个路径,如果其中某个目录能被普通用户写入,攻击者放一个同名文件进去,就有机会被服务加载。现在微软做了改动,这类问题少了一些,但服务相关目录权限过松的现象仍然很普遍。
计划任务的逻辑类似。计划任务可以配置为以SYSTEM身份运行某个脚本或程序,如果普通用户能在计划任务配置可写的脚本目录里放文件,或者任务本身允许普通用户修改,就等于给了攻击者一个高权限执行入口。检查这一类提权点时,我会重点看两处:一是服务二进制路径所在目录的ACL,二是计划任务的“运行身份”和“操作”中指向的程序路径。
2.3 令牌与账户机制滥用
讲到账户机制,就绕不开Windows的特权体系。某些特权本身的设计初衷是给系统服务管理员使用的,但如果在普通账户上配置不当,就会被攻击者用来提权。
最典型的是SeImpersonatePrivilege,也就是“模拟客户端”特权。这个特权允许进程临时借用其他用户的访问令牌来执行操作。很多Windows服务默认拥有这个特权,比如IIS应用池账户、SQL Server服务账户。攻击者一旦拿到这类权限,不需要知道SYSTEM密码,而是通过命名管道等方式诱使SYSTEM进程与自己通信,再借机模拟SYSTEM令牌,从而获得系统权限。这个方向上出现过大量利用工具,核心都不是系统漏洞,而是“服务账户自带特权”被滥用。
与此类似的还有SeDebugPrivilege,拥有该特权的进程可以打开其他进程的句柄,读取和修改其内存。如果一个服务账户或管理员账户被攻击者控制,他可以直接对着某个SYSTEM进程做进程注入,获得同等权限。SeBackupPrivilege、SeRestorePrivilege、SeTakeOwnershipPrivilege等也都属于高风险特权,一旦被低权限进程掌握,绕开文件系统ACL读取敏感文件不是难事。
日常加固时,我建议把所有非必要服务账户的特权列出来,凡是能用受限令牌解决的问题,就不要给宽泛特权。对运维人员来说,多一个特权、少一个特权看起来好像影响不大,但对攻击者来说,这两个特权之间的差距可能就是“普通用户”和“全盘接管”之间的差距。
2.4 第三方软件与DLL劫持
还有一类提权不依赖操作系统本身,而是依赖业务机器上安装的第三方软件。大型内网里,几乎每台机器都装了杀毒软件、办公软件、打印程序、驱动工具、远程控制程序。这些软件为了更新和兼容,往往有一些以高权限运行的进程和服务,目录结构也可能存在权限问题。
DLL劫持是其中容易被忽视的一条路。Windows进程在启动时会按照既定顺序加载DLL,包括系统目录、应用程序目录、当前工作目录等。如果应用程序目录允许普通用户写入,低权限用户就可以把一个恶意DLL放到该目录下,并起一个高权限进程启动时会自动加载的名字。等用户或系统触发进程启动,恶意DLL就在高权限进程里被加载执行。问题在于很多软件安装时会默认给当前登录用户写权限,而这类问题又不像内核漏洞那样有补丁可打。
另一个相关场景是“第三方驱动”。有些驱动的版本较老、存在漏洞,攻击者可以利用驱动漏洞直接与内核交互。因为驱动运行在内核级别,一旦加载成功,提权就完成了。在Windows 10以上系统中,微软对驱动的签名校验越来越严,但老版本驱动签名文件一旦被窃用,依然可能被加载。用AppLocker或WDAC限制驱动加载,在这里能起到不小的作用。
3. 防御视角的检查清单与加固手段
3.1 系统与补丁基线
先给一套可落地的检查思路。补丁管理不能只看“安装了多少条更新”,要看“所有机器是否在一个统一基线之上”。
- 用WSUS、企业更新服务或端点管理平台,把Windows工作站和服务器统一纳入更新部署。
- 对所有机器设置合理的补丁部署时间窗口,服务器优先考虑维护窗口,但工作站必须保证自动安装。
- 记录每台机器的操作系统版本、补丁版本,建立资产清单。没有资产清单,补丁管理就是空话。
- 对无法升级的旧系统,至少通过网络微隔离和主机防火墙限制访问来源,降低被利用概率。
我见过一个小型公司,把所有服务器都列进了补丁计划,但办公网两百台电脑常年没人管。后来一次演练里,一条基于旧版本漏洞的攻击链从办公电脑打到核心服务器,过程不到半小时。原因就出在终端补丁滞后。窗口期再短,也扛不住长期不更新的机器。
3.2 服务与开机项权限收敛
服务配置加固是本地提权防御里投入产出比最高的一项。建议按下面几步定期检查:
- 枚举系统中以SYSTEM或高权限账户运行的第三方服务。PowerShell一条命令就能列出服务名、显示名、启动方式和进程路径,重点关注路径不在系统目录的项。
- 检查服务二进制路径所在目录的ACL。可以用
icacls查看目录权限,如果发现Users或Everyone有写入权限,立即收紧到仅Administrators、SYSTEM和安装账户。 - 使用
sc.exe sdshow 服务名查看服务本身的安全描述符,配合工具确认哪些用户能修改服务配置。对不必要的服务,把修改权限从普通用户身上拿掉。 - 检查计划任务。用任务计划程序导出所有任务清单,逐个核对运行身份和操作中调用的脚本路径,确认这些路径不落在普通用户可写的目录内。
这样的检查不能只做一次。第三方软件每次升级可能重置目录权限,运维脚本也可能顺手给某个文件夹授权过宽。我把服务权限检查放进每月安全巡检,碰到可疑项当场修复,排查效率会高很多。
3.3 本地策略与账户管控
账户层面的加固思路很简单:让低权限账户保持低权限,让高权限账户只做高权限的事。
具体来说,普通业务用户不要加入本地管理员组。很多人为了方便,会把某个用户的电脑临时加一个管理员权限,之后却忘记撤掉。这是很危险的,因为一旦这台电脑被入侵,攻击者可能直接拿到管理员令牌。工作场景中需要管理员权限时,应该使用独立的管理员账户,或通过UAC临时提升,而不是让普通账户整天以管理员身份运行。
服务账户建议使用托管服务账户(gMSA)或虚拟账户,这类账户密码由系统管理,无法被人为读取,也不适合交互登录。风险在于有些老旧应用不支持,只能在服务账户密码上做强策略、定期轮换。另一个容易被忽略的点是本地管理员密码统一。企业内网如果有成百上千台机器都使用同一个本地管理员口令,攻击者提权到管理员后就能借助口令复用横向横扫。使用LAPS或类似方案自动轮换每台机器的本地管理员密码,可以把这种风险压到最低。
3.4 应用白名单与防护软件
补丁补不上、配置封不死的时候,最后一道防线是“不让未知代码运行”。
Windows自带的AppLocker或WDAC可以把进程执行限制在白名单范围内。默认情况下,用户临时目录和下载目录中的可执行文件不允许运行,很多提权工具第一步直接失败,因为它们需要从磁盘执行一个exe或调用powershell加载脚本。当然,启用白名单需要一个适配期,但一旦把常用软件和更新程序加入白名单,对安全收益非常明显。
另外,EDR(端点检测与响应)产品可以监控进程的完整调用链。比如攻击者从IIS进程启动一个PowerShell,再由PowerShell创建服务并启动恶意程序,这类“低权限进程创建高完整性进程”的行为,在正常业务中很少出现,却往往是提权的标志性动作。开启Windows事件日志的进程创建和命令行审计,配合Sysmon,能在日志层面补足这类检测点。如果预算有限,至少也要把系统内置审计打开,把安全事件日志转发到集中平台保存。
4. 检测与应急排查实录
4.1 常见入侵痕迹
本地提权不是无声无息的,至少会在日志和行为上留下较明显的线索。我经常看的几个地方:
- 安全日志中出现新用户创建,或现有用户被添加到Administrators、Remote Desktop Users等敏感组。
- 系统日志中出现了新服务安装记录,服务路径指向Temp目录、Public目录或用户下载目录。
- 计划任务目录里出现新任务,任务操作是执行某个脚本或从网络下载文件。
- 进程树中出现异常父子关系,比如
svchost启动了一个cmd,cmd又启动了PowerShell并连接外部地址。 - 注册表
Run、RunOnce、服务项和WMI持久化列表中出现陌生项。
这些痕迹单独看可能被误报淹没,如果组合在一起,尤其是一个正常服务进程启动了一个very短命的PowerShell进程,之后又出现了新服务,基本可以判定出问题了。
4.2 日志检查与事件ID速查
先整理一个我自己常用的事件ID表,对照排查会比较快:
| 日志类型 | 事件ID | 含义 |
|---|---|---|
| 安全日志 | 4672 | 为账户授予特殊权限 |
| 安全日志 | 4673 | 特权服务被调用 |
| 安全日志 | 4720 | 创建用户账户 |
| 安全日志 | 4732 | 用户被添加到安全组 |
| 安全日志 | 4688 | 进程创建(需开启命令行审计) |
| 系统日志 | 7045 | 安装新服务 |
| 系统日志 | 4697 | 服务安装(需配置审核) |
| PowerShell日志 | 4104 | Script Block记录 |
| Sysmon | 1 / 7 | 进程创建 / 镜像加载 |
要让4688带命令行参数,需要在组策略里开启“审核进程创建”并勾选“包括命令行”。这个开关很关键,没有命令行审计,攻击者执行了什么操作都看不全。Sysmon的镜像加载事件还能看到DLL加载情况,对发现DLL劫持极有帮助。
4.3 一次提权攻击的排查流程实录
有一次演练,某台Windows Server上的IIS进程突然生成了一个PowerShell进程,几秒钟后又创建了一个名为“UpdateHelper”的服务,服务路径指向C:\Windows\Temp\update.exe。这个行为特征太典型了,基本可以断定攻击者已经完成提权并通过服务做了持久化。我当时按这个顺序排查:
- 先冻结现场:保存进程列表、网络连接、内存转储,不让主机继续运行可疑任务。
- 查看Web日志和应用池权限,定位webshell来源,确认攻击入口。
- 用服务查询命令查看“UpdateHelper”的配置,确认服务启动账户是SYSTEM,路径指向临时目录。
- 查看系统补丁记录,判断是否存在近期公开的内核漏洞,确认提权时间线。
- 集中拉取该主机安全日志和Sysmon日志,找PowerShell进程启动前后的完整执行链路。
- 对外断开主机网络的写方向,保留必要出口供取证,同时封锁来源IP。
最终结论是攻击者通过Web漏洞进入,以内核漏洞完成提权,再创建服务作为持久化后门。处置策略也很明确:重装系统、重置所有在本机登录过的账号口令、对同网段主机做批量排查,后续再在Web层和服务层做加固。这类流程并不复杂,但每一步都需要日志留得足够全,否则只能看到表象,没法定位根因。
5. 加固时容易忽略的几个细节
说几个我在实际项目里反复踩过、也反复提醒别人的细节。
第一,只装补丁不收敛服务权限,防御效果会打折扣。补丁解决的是已知漏洞,服务权限问题解决的是“哪怕你知道漏洞也没法容易利用”的问题。即使没有内核漏洞,一个普通用户可写的服务路径也能让攻击者轻松提权。所以补丁和配置收敛必须同步做。
第二,检测规则不要只盯命令行。攻击者知道蓝队会监控whoami、systeminfo这一类基础命令,他们会用混淆的脚本、把命令拆成多段、通过WMI或.NET函数间接执行。与其死盯关键字,不如看父子进程和访问令牌变化。低权限进程创建高权限进程,这个行为本身比“执行了某个命令”更有价值。
第三,计划任务和服务不只在Windows服务管理器里查。攻击者可以用WMI、COM接口或注册表直接注册持久化,不一定走常规服务对话框。查可疑持久化时,除了“服务”面板,还要看HKLM\SYSTEM\CurrentControlSet\Services、计划任务目录、WMI筛选器,以及启动文件夹。
第四,账户和权限管理要从全局角度看,不能只看单台机器。A机器本地管理员密码和B机器一样,攻击者提权到A以后直接登录B,这种横向路径非常常见。本地管理员密码轮换、域管账户不得在工作站交互登录,这些策略虽然麻烦,但能有效切断横向移动链条。
本地提权这个题目,说到底不是“某一台机器”的事,而是整套身份权限体系和运维基线的事。每次保护措施升级,攻击者都会去寻找新的配置失误,防守方能做的就是不断缩小可被滥用的面,同时把日志和检测做厚。我在实际处理中体会最深的一点是,本地提权里最危险的往往不是0day,而是那些长期没人过问的服务权限、积压未打的补丁,以及没开命令行审计的Windows主机。与其等告警出现再手忙脚乱,不如先把这些基础项清理一遍。最后再分享一个小技巧:给所有本地管理员账户开启会话审计,并定期把安全日志备份到独立平台。只要日志还在,即便攻击者把手脚清理得再干净,也总能在某个角落里找到他来过的那条记录。