ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Windows内网提权实战:从配置错误到漏洞利用的完整思路

Windows内网提权实战:从配置错误到漏洞利用的完整思路

1. 提权前先看清楚:Windows内网里"权"到底指什么

做内网安全评估和攻防演练的朋友都清楚,拿到一台机器的普通用户权限只是起点,真正决定后续动作上限的,是你能不能从"普通用户"变成"管理员"甚至"SYSTEM"。这个跨越的过程就是提权。但很多刚接触这块内容的同学容易犯一个毛病——上来就翻漏洞列表、跑扫描工具,结果往往折腾半天一无所获。原因很简单:你没有先搞清楚目标机器上"权"的分布形态,自然不知道该往哪个方向使劲。

Windows的权限体系不像Linux那样单纯靠UID和GID区分,它是一套组合拳:访问令牌(Token)、访问控制列表(ACL)、特权(Privilege)三者共同决定了某个进程能做什么、不能做什么。普通用户登录后,系统会为其生成一个包含用户SID、组SID和特权列表的Token。提权的本质,说穿了就是想办法让你手里的Token"扩容"——要么拿到更高权限的Token,要么让现有Token被赋予额外的特权,要么直接找到一条能借高权限进程帮你干活的路径。

这里给大家一个最基础的判断框架,用于快速确定排查方向:

当前状态优先排查方向说明
补丁严重滞后系统漏洞系统本身存在已知权限提升漏洞
补丁及时、系统较新配置错误服务、目录、计划任务等的权限配置问题
机器上装有大量第三方软件第三方软件以高权限运行的服务、驱动、软件更新组件
机器是域内主机域相关配置本机提权+域内横向路径结合分析

我个人在实际排查中的经验是:先看配置错误,再看漏洞。原因后面会详细讲,但简单说一句——配置错误是"作者忘了锁门",漏洞提权是"破窗而入",你永远应该先试试门能不能推开。

2. 配置错误提权:最常见也最好利用的一类入口

配置错误提权之所以排在所有思路前面,是因为它不需要考虑系统补丁版本,不需要对抗防护软件,纯粹是"有没有粗心大意留下的口子"。这个口子只要存在,利用成本低得惊人。

2.1 服务路径配置不当与未引号服务路径

这是经典中的经典。Windows服务在注册表里记录了自己的启动路径,如果路径中包含空格且没有用双引号包裹完整路径,系统在启动服务时就会按空格拆分路径去查找可执行文件。举个例子,假设有个服务指向:

C:\Program Files\My Business App\service.exe

如果注册表里写的是未加引号的完整字符串,Windows在解析时会依次尝试:

C:\Program.exe C:\Program Files\My.exe C:\Program Files\My Business\App\service.exe

注意,当前用户对C:\根目录如果有写权限,那就可以放一个名为 Program.exe 的恶意程序到C盘根目录,然后想办法重启服务或诱导服务重启,服务就会以SYSTEM权限加载你的程序。难点在于:现代系统默认普通用户对C:\根目录没有写权限,所以这个经典利用在一些环境下会失败。

排查命令很简单,用wmic就能拿到全部服务信息:

wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows\\" | findstr /i /v """

这条命令的目的是筛选出非系统自带、开机自启、且路径值里不带引号的服务。拿到结果后逐一确认目标服务对应目录的ACL权限。如果发现"当前用户可以对服务文件所在文件夹进行写入",那就满足条件了。

提示:即使服务路径带了完整引号,也值得检查服务二进制文件本身是否允许普通用户替换。如果服务以SYSTEM身份运行、文件可写,替换成自己的程序再触发重启,效果一样。

2.2 注册表自启动项与映像劫持

HKLM\Software\Microsoft\Windows\CurrentVersion\Run 下的自启动项人人都知道,但容易被忽略的是HKLM\SYSTEM\CurrentControlSet\Services下的服务参数项。某些第三方软件会把服务相关的配置写在可被低权限用户修改的位置,典型的就是ImagePath值——如果这个值的写权限放开给了User组,那就能直接改掉服务启动的程序路径,让服务下次启动时加载你的程序。

实际检测时,我会先检查目标文件夹的权限:

icacls "C:\Program Files\某第三方软件"

如果输出里出现BUILTIN\Users:(F)或者Everyone:(F)这种字样,基本可以宣告沦陷。这类问题常见于一些老旧的生产管理软件、门禁系统、打印管理软件,它们为了"方便更新"直接把整个安装目录授权给了普通用户。

2.3 计划任务指向可写目录

计划任务的排查思路和服务类似。攻击者会关注两类:一是普通用户可创建的计划任务(配合高权限运行),二是已有的计划任务指向了可写的脚本或程序。在实战中,问题往往出在第二种——管理员新建了一个计划任务备份数据库,调用的脚本放在了一个普通用户可写的共享目录里,然后计划任务以SYSTEM身份执行。这种情况下,改脚本内容等于直接拿到SYSTEM执行权限。

排查时可以重点看:

schtasks /query /fo LIST /v

检查其中"要运行的任务"路径,逐一确认脚本目录权限。需要注意,某些计划任务只在特定条件下触发(如系统空闲、用户登录、某事件日志产生),触发条件不同,等待成本也不同。有条件的话,直接在权限可控范围内模拟触发条件,能省去大量等待时间。

2.4 服务对象权限过宽

这条容易被忽略,但杀伤力不小。服务本身在Windows中也是一个对象,有独立的ACL。正常情况下普通用户只能启动、停止部分服务,但偶尔会有配置错误导致普通用户拥有对某个服务的SERVICE_CHANGE_CONFIG权限,意思是你可以修改这个服务的配置——包括它启动时运行什么程序。

利用方式也非常直接:

sc config 某服务 binPath= "cmd /c whoami > C:\temp\result.txt" sc start 某服务

服务一启动,命令就以该服务账户的权限执行了。如果这个服务恰好以LocalSystem运行,效果等同于直接拿到系统最高权限。

3. 漏洞提权:哪些漏洞值得关注,哪些只是噪音

配置错误排查完了,如果还没有收获,才会考虑漏洞提权。但漏洞提权不是"扫到过期漏洞列表就往机器上砸",那样效率很低且容易被拦截。

3.1 系统内核漏洞:补丁基线是第一判断依据

Windows内核漏洞的利用通常绕过或攻击某个系统组件,最终以SYSTEM权限执行代码。这类漏洞的特点是:影响面广、修复快、补丁一打就失效。因此判断思路应该是:

  • 先抓取目标系统的补丁安装列表;
  • 对比已知受影响版本范围;
  • 只对命中范围内的漏洞做进一步验证。

补丁列表抓取:

wmic qfe list full

拿到列表后关注两个信息:安装日期和HotFixID。如果目标机器最近一次补丁更新已经是几个月甚至一年前的事,那系统大概率存在可利用的已知漏洞。但这里有个很现实的问题:即使存在一个知名漏洞,利用公开EXP的成功率也受系统架构、防护软件、系统完整性等多方面影响,并不是"有漏洞就一定能打下来"。

在授权测试中,我的策略是——优先尝试那些利用链短、依赖条件少的漏洞类型,而不是一上来就跑各种自动化利用框架。很多自动化工具在目标机器上动静太大,很容易触发防护告警。

3.2 第三方软件与服务的高权限执行

比起系统内核漏洞,我更关注目标机器上安装了哪些以高权限运行的第三方软件,尤其是这几类:

  • 杀毒软件、终端管理软件(它们的内核驱动和更新服务是高价值目标);
  • 数据库软件(通常以服务方式运行,且拥有高权限);
  • 打印管理、文档管理、老旧OA组件(权限意识淡薄的重灾区);
  • 带有自动更新功能的常用工具软件。

这类软件一旦存在任意文件写入、DLL劫持、命令注入类问题,利用门槛往往比内核漏洞低很多。搜索思路是:先枚举安装目录、服务列表、计划任务,找到第三方软件的形态,再逐个确认它们的文件权限、服务账户、是否有web管理面板等。

3.3 通俗理解漏洞提权的本质

如果打个比方,配置错误是"主人出门忘锁门",那漏洞提权就是"主人锁了门,但窗户玻璃一碰就碎"。内核漏洞利用,本质上就是在跟系统的安全机制玩"谁先发现谁的漏洞"的游戏。系统补丁就像是给窗户装防盗网,补丁一旦更新,原来的突破口就封死了。所以漏洞提权非常看重信息收集的时效性——你面对的系统是什么版本、打了哪些补丁、处于什么样的运行环境,所有这些都直接影响漏洞是否可用。

4. 一次授权靶机上的完整提权复盘

理论说再多,不如走一遍实际过程。下面是我在某次授权测试中的一次完整复盘,环境和目标信息做了脱敏处理,但整个链路是真实发生的。

4.1 信息收集阶段

目标是一台Windows Server 2019机器,补丁停留在半年前。拿到的初始权限是某应用服务的本地普通账户。我的信息收集顺序是:

  1. 当前用户及权限组:whoami /all;
  2. 系统补丁列表:wmic qfe list;
  3. 服务列表及路径:wmic service list full;
  4. 计划任务列表:schtasks /query /fo LIST /v;
  5. 目录权限抽查:icacls "C:\Program Files\*";
  6. 网络连接与域环境:ipconfig /all、netstat -ano、systeminfo。

做完这些,我心里就有了大致判断:系统补丁有半年空窗期,确实存在已知漏洞的可能;不过服务列表里有一个非系统自带服务,路径指向某个第三方管理软件目录。

4.2 发现服务路径可写

那个第三方软件的安装目录权限输出如下:

C:\Program Files\某管理软件\ C:\Program Files\某管理软件\BUILTIN\Users:(OI)(CI)(F)

(OI)(CI)(F)表示子文件夹和文件继承完全控制权限。普通用户对这个目录下的文件拥有完全控制权。更关键的是,服务本身以LocalSystem身份运行。

这类问题在真实环境中出现频率极高。很多运维为了方便软件升级,直接给整个安装目录开了Users完全控制权限,却完全没意识到这等于把服务执行权交给了机器上的每一个普通账户。

4.3 替换文件触发服务重启

确认服务启动模式为"自动",且当前状态是"已停止"。我原计划替换服务主程序文件,但考虑到直接替换可能导致软件完整性校验失败被察觉,于是调整思路:不碰原始文件,改走DLL劫持路线——在服务启动时优先加载的目录里放置同名DLL,把恶意逻辑放在DLL的导出函数里。

具体来说,我先用工具查看了该服务主程序的导入函数,找到了一个不太常见但一定会被加载的系统DLL,然后在服务程序目录里放了同名的自定义DLL。服务一启动,恶意DLL被加载,代码在SYSTEM上下文执行。

因为这个服务的启动方式设为"自动",在等待一个业务触发条件后,服务正常拉起,目标代码成功执行。整个过程没有改动任何现有文件,对业务的干扰被降到最低。

4.4 复盘结论

这条路径的成功,依赖三点:服务以高权限运行、服务文件目录可写、服务会被正常触发启动。三者缺一,过程都会变复杂。

5. 防御视角:如何把这些提权路径全部堵上

从防御方的角度,做一次"自我体检",比研究攻击手法更紧迫。因为攻击者只要找到一个点就能深入,而防守方需要把所有口子都堵上。下面是我写在加固清单里的内容,每一条都对应一种实战中常见的提权路径。

5.1 权限最小化和ACL定期审计

服务、计划任务、注册表键值对应的可执行文件目录,必须严格限制写权限。建议梳理出所有以高权限运行的服务和计划任务,逐一检查其路径目录ACL。可以建立一个定期扫描机制,每周自动收集一次关键目录、关键注册表项的权限情况,出现异常变动立即告警。

具体操作上,使用icacls回收不必要的权限:

icacls "C:\Program Files\某软件" /remove "BUILTIN\Users" icacls "C:\Program Files\某软件" /inheritance:r

/inheritance:r是移除继承权限,避免上层目录放开后再次扩散。注意操作前一定要确认软件运行账户仍然有足够权限,否则会导致软件无法启动,这类误伤事故在实际运维中非常常见。

5.2 服务与计划任务加固检查表

检查项合格标准
服务路径是否加引号所有含空格路径必须用双引号包裹
服务二进制文件权限仅允许SYSTEM/Administrators修改
服务配置权限普通用户无SERVICE_CHANGE_CONFIG权限
计划任务脚本目录脚本所在目录仅允许管理员写入
注册表服务项权限ImagePath等键值仅允许SYSTEM修改

这份清单不需要每天看,但每次变更发布后都过一遍,成本很低,收益很高。

5.3 补丁管理和漏洞生命周期

补丁管理不是"装了就完"。实际运行经验告诉我,真正危险的不是"没打补丁"这个事实,而是安全团队不知道哪些机器没打补丁。建议建立基础补丁台账,至少覆盖:系统版本、最近补丁日期、缺失的严重级别补丁数量。可以按月生成一次报告,再对照已知漏洞清单做交叉比对,输出"当前环境中高概率受影响资产列表"。

另外有个细节值得注意:第三方软件的补丁比系统补丁更容易被忽略。浏览器插件、Java运行时、PDF阅读器、压缩工具这些经常被普通用户使用的组件,一旦存在提权漏洞,影响面往往大于系统漏洞。这类软件的版本搜集和更新,建议纳入统一软件管理平台,而不是靠运维手工维护。

5.4 攻击面收敛

每台服务器上安装的软件、开放的服务、创建的计划任务,都应该有明确的"存在理由"。一个很残酷的事实是,大部分被利用的点,根本不是业务必须的。比如某台业务服务器上装了远程管理软件、团队沟通软件、浏览器、压缩工具,这些软件每一个都增加了攻击面。收敛攻击面的原则很简单:不用的服务和软件一律移除,确实要用的则按上面的权限最小化原则进行加固。

6. 关于实操的几点提醒

在文章的最后,说一些我在实际项目中反复踩过的坑,这些东西在常规文档里往往不会写,但对实际操作很有帮助。

第一,先判断目标环境的真实情况,再决定工具链。很多自动化扫描工具号称"一键检测",但在防护软件齐全、网络隔离严格的内网环境里,自动化工具不仅可能被拦截,还可能直接触发告警,导致整个测试计划提前暴露。相比之下,手工信息收集虽然慢,但动静小、可控性强,是更稳妥的方式。

第二,授权测试务必清楚边界。无论做什么操作,都应当在授权范围和授权时间内进行。碰到拿不准的情况,宁可停下来和授权方确认,也不要为了"展示能力"去越界操作。这是底线,也是最基本的安全意识。

第三,搭建自己的靶机环境反复练手。无论是配置错误还是漏洞利用,熟不熟练直接影响效率。我建议在本地用虚拟机搭一套Windows Server环境,里面故意留几个典型的配置错误——比如放开Users权限的服务目录、未加引号的服务路径、可写的计划任务脚本——然后反复练习从信息收集到提权的完整过程。

用合法靶机练手、在授权范围内实战,这两条路都能积累经验。但一定不要在未经授权的环境里测试这些东西,这既是合规问题,也关系到你作为安全从业者的职业信誉。

我在实际测试中的体会是:内网提权拼的从来不是单一漏洞的利用能力,而是对系统运行细节的理解程度。同一个目录权限,在日志审计上留下的痕迹完全不同;同一条命令,在不同版本系统上的行为也有差异。能把细节抓得越准,后面走的路就越顺。如果这篇文章能帮你少走两步弯路,就没白写。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进