Windows本地提权:Rotten Potato原理、编译与实战应用

发布时间:2026/6/26 11:08:57
Windows本地提权:Rotten Potato原理、编译与实战应用 1. 项目概述从“烂土豆”到权限提升的利器如果你在渗透测试或者红队评估中遇到过Windows系统上获取了某个服务账户比如IIS的应用池账户、SQL Server服务账户的权限却发现自己被困在一个低权限的“牢笼”里无法进一步提权到SYSTEM那么“Rotten Potato”烂土豆这个名字你肯定不会陌生。这可不是什么烹饪教程而是一个在特定场景下极具威力的本地权限提升Local Privilege Escalation LPE漏洞利用工具。它的核心是巧妙地利用了Windows操作系统中COMComponent Object Model组件的一些特性通过令牌模拟Token Impersonation和权限劫持将我们手头有限的权限“发酵”成至高无上的SYSTEM权限。简单来说Rotten Potato利用的是一个经典的“土豆”系列提权链的变种。它不依赖于系统未打补丁的远程漏洞而是利用Windows自身机制在本地发起的攻击。当你已经能够在目标机器上执行代码比如通过Web Shell、恶意文档宏、或者已经攻陷的服务但当前进程的权限较低时Rotten Potato提供了一种可能性诱使一个更高权限的系统组件比如本地RPC服务连接到我们控制的“陷阱”中然后窃取其安全令牌Token最终实现权限跃迁。这个过程听起来有点复杂但工具本身的使用却相对直接这也是它备受安全研究人员和渗透测试人员关注的原因。这篇文章我将从一个实战者的角度带你彻底拆解Rotten Potato的安装、原理、使用场景以及那些容易踩坑的细节。无论你是刚开始接触内网渗透的新手还是想深入了解Windows安全机制的老兵相信都能从中获得一些可以直接用于实战的干货。我们会从环境准备开始一步步走到编译、使用和问题排查过程中我会穿插大量我实际测试中遇到的“坑”和解决技巧。2. 核心原理与前置知识拆解在动手安装和运行任何工具之前理解其背后的原理至关重要。这不仅有助于你在不同环境下灵活变通更能让你在工具失效时自己找到排查方向甚至创造新的利用方式。Rotten Potato的核心建立在几个关键的Windows安全概念之上。2.1 安全令牌Security Token与模拟Impersonation在Windows中每个进程和线程都有一个与之关联的安全令牌。这个令牌就像你的身份证里面包含了你的用户身份SID、所属组、特权Privileges等信息。系统根据令牌来决定这个进程能访问哪些资源如文件、注册表键。“模拟”是一个关键机制。它允许一个进程或线程在某个操作中“扮演”另一个用户的安全上下文。例如一个服务进程以SYSTEM权限运行当它需要代表某个普通用户访问网络资源时它可以模拟该用户的令牌去执行操作。Rotten Potato的目标就是让我们控制的低权限进程能够模拟一个高权限通常是SYSTEM的令牌。2.2 COM与RPC通信的桥梁COM和RPCRemote Procedure Call是Windows内部组件间通信的基石。很多系统服务都通过RPC暴露接口。当低权限进程需要与高权限服务通信时Windows会创建一个名为“NT AUTHORITY\SYSTEM”的“网络服务”或“本地服务”账户的上下文来处理某些类型的身份验证请求特别是NTLM认证。这里就存在一个机会窗口如果我们能欺骗系统让一个高权限的服务来连接我们控制的、正在监听特定端口的进程我们就有可能截获这个高权限的上下文。2.3 “土豆”系列漏洞的本质从Juicy Potato到Rotten Potato最初的“Hot Potato”利用的是WPAD、NBNS欺骗和NTLM重放。而后续的“Juicy Potato”及其变种“Rotten Potato”核心思路是滥用COM组件的权限设置和DCOM激活机制。在Windows中许多COM对象被配置为可以由“NT AUTHORITY\NETWORK SERVICE”或“NT AUTHORITY\LOCAL SERVICE”账户激活。如果我们拥有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege特权这在许多服务账户如IIS的默认应用池账户中很常见我们就可以创建一个COM服务器并诱使一个以SYSTEM权限运行的DCOM客户端连接到我们这里。Rotten Potato是Juicy Potato的一个特定实现或变种它通常指代一种利用方法通过特定的CLSIDClass ID COM对象的全局唯一标识符和操作序列触发一个本地RPC调用该调用最终会以SYSTEM身份尝试连接到我们指定的端口。一旦连接建立我们就可以通过一系列Windows API调用如AcceptSecurityContext和ImpersonateSecurityContext来窃取并模拟这个SYSTEM令牌。关键点成功利用通常需要两个条件1. 当前进程持有SeImpersonatePrivilege特权2. 系统中存在可被滥用的、配置了特定权限的COM对象。IIS、SQL Server等服务账户通常默认具备这些条件。2.4 为什么需要编译安装你可能会在网上找到一些预编译的rottenpotato.exe二进制文件。但从安全性和可控性角度我强烈建议你自己从源码编译。原因有三第一预编译的二进制文件可能被植入后门在渗透测试中使用来历不明的工具是极度危险的第二不同的Windows环境如Windows Server 2012 R2, 2016, 2019, Win10不同版本可能需要微调代码或编译参数自己编译可以灵活适配第三理解编译过程能帮助你更好地理解这个工具依赖了哪些库和API在遇到问题时能更快定位。3. 环境准备与源码获取工欲善其事必先利其器。为Rotten Potato准备编译环境我们需要两样东西一是源码二是合适的编译工具链。3.1 获取源代码Rotten Potato的源码通常托管在GitHub上。由于项目可能有多人维护的多个分支寻找一个活跃且稳定的版本很重要。你可以使用Git克隆或者直接下载ZIP压缩包。假设我们在一个已经具备基本开发环境的测试机器可以是攻击机也可以是被控机的临时目录上操作。打开命令行CMD或PowerShell执行以下命令git clone https://github.com/breenmachine/RottenPotatoNG.git cd RottenPotatoNG注意实际的仓库地址可能变化。RottenPotatoNG是一个常见的、功能较全的分支。如果这个仓库失效可以尝试搜索“RottenPotato”或“JuicyPotato”的其他分支。务必从看起来官方或星标数较高的仓库获取代码以降低风险。3.2 编译工具链选择Visual Studio vs. MinGW在Windows上编译C/C项目主要有两大选择微软官方的Visual Studio及其命令行工具cl.exe和MinGW-w64GCC for Windows。Visual Studio推荐这是最“原生”的方式与Windows API兼容性最好。你需要安装Visual Studio社区版即可并确保安装了“使用C的桌面开发”工作负载。编译时我们需要使用Developer Command Prompt for VS或Developer PowerShell因为它们正确配置了cl、link等编译工具和库的路径。MinGW-w64这是一个跨平台的编译环境。如果你习惯GCC套件或者你的攻击机是Linux但需要通过交叉编译生成Windows可执行文件MinGW是很好的选择。但在编译严重依赖特定版本Windows SDK的项目时可能会遇到一些头文件或库链接问题。对于Rotten Potato这种深度依赖Windows安全API如sspicli.lib,secur32.lib的工具我强烈建议使用Visual Studio进行编译能省去很多不必要的麻烦。下文也将以VS为例。3.3 识别项目结构进入源码目录后先看看文件结构。通常你会看到RottenPotato.cpp或main.cpp主程序源文件。RottenPotato.h或其他头文件声明函数和结构。common.h、utils.cpp等辅助函数和通用定义。可能还有一个README.md或Makefile。快速浏览README.md里面可能有重要的编译说明或依赖项。然后我们需要检查代码确认它是否需要额外的库。用文本编辑器打开主要的.cpp文件查看开头的#include部分。你很可能会看到类似这样的引用#include windows.h #include winsock2.h #include sspi.h #include security.h #include stdio.h这证实了它对Windows Socket、安全支持提供程序接口SSPI的依赖。4. 使用Visual Studio编译Rotten Potato现在进入核心的编译环节。我们将不使用完整的Visual Studio IDE而是用命令行完成这样更轻量也更容易在远程环境中复现。4.1 启动编译环境在开始菜单中找到“Developer Command Prompt for VS 20XX”XX是你的VS版本右键以管理员身份运行。虽然不一定每次都需要管理员权限但为了避免因权限问题导致的文件访问或注册表访问错误建议直接使用管理员命令行。然后使用cd命令导航到你的RottenPotatoNG源码目录cd C:\path\to\your\RottenPotatoNG4.2 执行编译命令编译一个简单的Windows控制台程序通常只需要cl.exe编译器。我们需要告诉编译器源文件、输出文件名、以及链接哪些库。一个最基本的编译命令如下cl.exe /nologo /Ox /MT /W0 /GS- /DNDEBUG /TcRottenPotato.cpp /link /OUT:rottenpotato.exe advapi32.lib secur32.lib ole32.lib oleaut32.lib user32.lib ws2_32.lib让我们拆解这个命令的每个部分/nologo禁止显示编译器的版权标志。/Ox启用最大优化让生成的exe更小、更快。/MT使用静态运行时库LIBCMT.LIB。这是关键使用/MT意味着将C运行时库静态链接到exe中这样生成的可执行文件就可以在不安装Visual C Redistributable的“干净”Windows系统上独立运行。对于渗透测试这几乎是必须的。/W0关闭所有警告信息。/GS-关闭缓冲区安全检查。某些安全工具或漏洞利用代码可能会因为GS保护而行为异常关闭它可以增加兼容性但略微降低程序本身的安全性对我们这个利用工具而言不重要。/DNDEBUG定义NDEBUG宏通常会禁用断言assert。/TcRottenPotato.cpp指定要编译的C源文件。如果是.cpp文件应使用/Tp。/link ...链接器选项。/OUT:rottenpotato.exe指定输出文件名。advapi32.lib secur32.lib ole32.lib oleaut32.lib user32.lib ws2_32.lib这是核心这些是Windows API库。advapi32高级API服务包括注册表和安全管理。secur32安全支持提供程序接口用于身份验证。ole32,oleaut32OLE和COM相关功能这是“土豆”利用链的核心。user32用户界面相关虽然我们不用GUI但某些基础API可能需要。ws2_32Windows Sockets 2用于网络通信。在Developer Command Prompt中执行上述命令。如果一切顺利你会在当前目录下看到rottenpotato.exe大小可能在几十KB到一百多KB。4.3 编译中可能遇到的错误与解决“无法打开源文件windows.h”或类似错误 这通常是因为命令行环境没有正确设置Windows SDK的包含路径。确保你启动的是Developer Command Prompt而不是普通的CMD或PowerShell。如果问题依旧可以尝试在VS Installer中修复安装确保安装了对应版本的Windows SDK。链接错误LNK2001: 无法解析的外部符号 ... 这通常是缺少对应的.lib库文件。仔细检查错误信息中提到的函数名。例如如果错误涉及CoInitializeSecurity那肯定需要ole32.lib。根据错误提示在/link后面添加相应的库。常见的还有rpcrt4.lib用于RPC、crypt32.lib用于加密等。你需要根据源码中实际调用的API来调整。源码本身的编译错误 不同分支的代码可能针对不同Windows版本。如果遇到语法错误或未定义的标识符可能是代码使用了较新编译器才支持的特性或者依赖了特定SDK版本。你可以尝试注释掉出错的代码行如果看起来不是核心功能。在GitHub上查看该项目的Issues或Pull Requests看是否有人修复过类似问题。切换到另一个更稳定的分支或仓库。我的实操心得我习惯在编译前先快速通读一遍主源码文件看看它包含了哪些头文件调用了哪些关键的Windows API。这样在遇到链接错误时我能快速反应需要链接哪个库。一个笨办法但有效把常用的库advapi32.lib, secur32.lib, ole32.lib, oleaut32.lib, user32.lib, ws2_32.lib, rpcrt4.lib, crypt32.lib都加上通常能解决大部分问题。5. 实战使用与参数详解编译出rottenpotato.exe后我们终于可以把它放到目标环境里试试了。但直接运行rottenpotato.exe很可能什么都不会发生或者弹出一个用法提示。我们需要理解它的参数。5.1 基本用法与参数解析运行rottenpotato.exe -h或直接运行通常会显示帮助信息。典型的参数可能包括rottenpotato.exe -l 监听端口 -p 要启动的程序路径 -a 程序参数 -t 类型 -c CLSID-l(listen port)指定一个本地端口用于等待高权限连接的到来。这是一个关键参数。通常需要指定一个未被占用的端口如9999。Rotten Potato会在这个端口上启动一个RPC服务器。-p(program)提权成功后你想要以SYSTEM权限运行的程序的路径。例如你想启动一个新的cmd.exe这里就填C:\Windows\System32\cmd.exe。-a(arguments)传递给上面程序的参数。对于cmd.exe你可能想让它执行一个命令然后退出可以传/c whoami。-t(type)指定利用的类型或触发方式。不同版本的Rotten Potato/Juicy Potato可能有不同的触发机制如t可能代表“测试”或某种特定协议。需要查阅具体版本的文档或源码。-c(CLSID)指定要滥用的COM对象的CLSID。这是另一个核心参数。不同的Windows版本和配置下可用的CLSID不同。Juicy Potato项目曾维护过一个CLSID列表对应不同系统的可用性。Rotten Potato可能内置了一个或多个默认的CLSID。一个最常见的用法示例 假设我们通过Web Shell上传了rottenpotato.exe到C:\temp\目录并且我们当前进程具备SeImpersonatePrivilege。我们想获取一个SYSTEM权限的cmd.exe。C:\temp\rottenpotato.exe -l 1337 -p C:\Windows\System32\cmd.exe -a “/c whoami C:\temp\output.txt” -t * -c {CLSID}这条命令的意思是在本地1337端口监听当成功窃取SYSTEM令牌后启动cmd.exe并执行命令whoami将结果输出到C:\temp\output.txt。-t *和-c {CLSID}需要根据实际情况替换。有时工具内置了默认的CLSID-c参数可以省略。5.2 关键步骤如何寻找有效的CLSIDCLSID是一个128位的全局唯一标识符格式如{XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}。对于“土豆”类漏洞我们需要寻找那些权限设置允许NT AUTHORITY\NETWORK SERVICE或NT AUTHORITY\LOCAL SERVICE甚至Everyone激活的COM对象。该对象在激活时会发起一个到本地的网络连接。如何找有几种方法使用工具枚举Juicy Potato的作者提供了一个GetCLSID.ps1PowerShell脚本可以枚举本地系统并测试CLSID。你可以上传这个脚本到目标机器运行如果PowerShell执行策略允许。查阅已知列表互联网上有安全研究人员分享的针对不同Windows版本的“可用CLSID”列表。例如{4991d34b-80a1-4291-83b6-3328366b9097}用于BITS服务在旧版本系统中常被使用。但请注意系统补丁、版本更新都会导致CLSID失效这份列表需要不断更新和测试。盲测与日志分析如果你没有现成列表可以尝试一些常见的CLSID并通过工具如Process Monitor观察进程行为看是否有SYSTEM权限的进程尝试连接你指定的端口。重要注意事项在实战中直接使用网上找到的CLSID列表可能成功率不高因为目标系统可能已打补丁或版本不同。最可靠的方法是在与目标环境相似的测试机上自己用PowerShell脚本枚举和验证。这是一个需要耐心和技巧的过程。5.3 利用链的完整过程模拟让我们在脑海中模拟一下一次成功的利用过程前提你已经以具备SeImpersonatePrivilege的账户如IIS AppPool\DefaultAppPool执行了命令。启动你运行rottenpotato.exe -l 9999 -p cmd.exe。监听Rotten Potato在后台创建Socket绑定到9999端口开始监听。触发Rotten Potato通过调用CoInitializeSecurity等API并可能使用指定的CLSID触发一个本地的DCOM/RPC激活请求。连接系统中某个以SYSTEM权限运行的组件例如RPCSS服务本身在处理这个激活请求时会尝试连接到127.0.0.1:9999或某个本地地址。窃取Rotten Potato的监听器接受这个连接。由于连接来自SYSTEM上下文它携带了SYSTEM的NTLM认证协商消息。Rotten Potato利用SSPI处理这个认证最终调用ImpersonateSecurityContext成功模拟SYSTEM令牌。执行在模拟的SYSTEM线程上下文中Rotten Potato创建新的进程cmd.exe这个新进程就拥有了SYSTEM权限。完成你得到了一个SYSTEM权限的cmd.exeshell。6. 典型应用场景与限制条件理解了原理和用法我们来看看Rotten Potato在什么情况下能大显身手又在什么情况下会无能为力。6.1 主要应用场景Web应用渗透后的提权这是最经典的场景。你通过漏洞如文件上传、SQL注入、反序列化在IIS服务器上获得了Web Shell当前权限是IIS APPPOOL\DefaultAppPool。这个账户默认拥有SeImpersonatePrivilege是Rotten Potato的完美目标。成功后可获得服务器最高权限。服务账户提权当你通过某种方式如弱口令、配置错误获得了某个Windows服务的执行权限例如一个以NT AUTHORITY\NETWORK SERVICE运行的自定义服务而这个服务账户也通常具备必要的特权。受限环境下的横向移动跳板在内网中你可能先控制了一台边缘服务器其上的服务账户权限有限。利用Rotten Potato提权到SYSTEM后可以转储本地哈希、抓取明文密码、查看敏感文件为横向移动到更重要的机器如域控制器创造条件。6.2 成功利用的必要条件与限制不是所有情况都能成功。你必须检查以下条件当前令牌持有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege特权这是硬性要求。你可以用whoami /priv命令查看。IIS应用池账户、SQL Server服务账户等通常都有。系统版本与补丁微软通过补丁如针对CVE-2019-0841等不断修复被滥用的COM组件。较新的Windows 10/11和打了最新补丁的Windows Server 2019/2022很多经典的CLSID已经失效。工具在未打补丁的Windows 7/8.1、Server 2008 R2/2012 R2上成功率更高。防火墙与网络策略利用过程涉及本地环回地址127.0.0.1的特定端口通信。通常Windows防火墙不会阻止本地回环流量但一些严格的安全策略或第三方主机防火墙可能会。如果失败可以尝试关闭防火墙netsh advfirewall set allprofiles state off测试但这在实战中可能不现实。防病毒软件Rotten Potato的行为监听端口、创建高权限进程很可能被AV/EDR检测。你需要做好免杀处理或者寻找其他提权路径。CLSID的可用性如前所述这是最大的变数。没有“万能”的CLSID。6.3 替代方案与衍生工具如果Rotten Potato因为补丁或CLSID问题失效不要灰心还有同系列的“土豆”可以尝试Juicy Potato功能更丰富内置了CLSID测试和多种触发方式是Rotten Potato的增强版。Sweet Potato将“土豆”系列技术集成到Cobalt Strike等攻击框架中。PrintSpoofer、PetitPotam利用其他Windows协议打印后台处理程序服务、MS-EFSRPC进行本地提权或NTLM中继思路不同但同样精彩。7. 常见问题排查与实战技巧在实际操作中你大概率不会一帆风顺。下面是我在多次测试中积累的一些常见问题排查思路和技巧。7.1 问题排查清单当你运行rottenpotato.exe后没有任何反应或者没有弹出SYSTEM权限的cmd.exe时请按以下顺序排查问题现象可能原因排查步骤程序运行后立即退出无输出1. 参数错误2. 依赖的DLL缺失如果动态编译3. 代码逻辑错误如CLSID无效1. 检查命令行参数是否正确特别是路径和CLSID格式。2. 使用/MT静态编译确保无运行时依赖。3. 尝试使用-t *或更换CLSID。在命令行末尾加21重定向错误输出到文件查看。程序运行显示监听端口但一直挂起无结果1. 指定的CLSID在当前系统无效。2. 当前进程没有SeImpersonatePrivilege。3. 防火墙/安全软件拦截。4. 系统已打补丁利用链被阻断。1. 运行whoami /priv确认特权。2. 尝试多个已知的CLSID需研究目标系统版本。3. 临时关闭防火墙测试。4. 使用Process Monitor监控rottenpotato.exe进程看是否有“ACCESS DENIED”或连接被拒绝的事件。弹出cmd.exe窗口但whoami显示不是SYSTEM模拟令牌失败。可能只窃取到了“NETWORK SERVICE”或“LOCAL SERVICE”的令牌而不是真正的SYSTEM。这有时也算部分成功但权限不够。尝试不同的-t触发类型或者换用Juicy Potato等更成熟的工具它们有更丰富的触发选项。被杀毒软件立即清除行为或特征码被识别。1. 对源码进行混淆、修改字符串、加壳后再编译需要一定的免杀知识。2. 使用内存加载反射DLL注入等方式不落地执行。7.2 实战技巧与心得“先测试后实战”在真实环境使用前务必在虚拟机中搭建一个与目标系统版本、补丁级别尽可能相似的环境进行测试。记录下有效的CLSID和参数。权限检查是第一步拿到Shell后别急着运行提权工具。先whoami /priv看看有没有SeImpersonatePrivilege。如果没有Rotten Potato基本没戏趁早换其他提权思路如内核漏洞、服务配置错误等。端口选择-l参数指定的端口尽量选1024以上的高端口避免与系统服务冲突。同时确保这个端口没有被占用。你可以先用netstat -ano | findstr :端口号检查一下。从Web Shell执行时的陷阱如果你通过Web Shell如aspx, php执行rottenpotato.exe要注意Web服务进程如w3wp.exe可能受到资源限制或沙盒限制可能无法成功创建监听套接字或新进程。尝试将可执行文件下载到可写目录如C:\Windows\Temp\再执行。使用管道接收结果在不能直接弹出交互式Shell的场合如某些Web Shell你可以让提权后的命令将结果写入文件再读取。例如-a “/c ipconfig C:\temp\result.txt 21”。组合利用提权到SYSTEM后第一时间应该做什么我的习惯是转储密码哈希使用reg save导出SAM和SYSTEM文件或使用mimikatz查看计划任务、安装的软件、网络连接为下一步横向移动做准备。保持更新Windows在持续更新提权技术也在演变。Rotten Potato可能在某些最新系统上完全失效。要关注安全社区的新研究比如近年来基于EFSRPC、Shadow Credentials的提权方法。8. 防御视角如何防范此类攻击作为一名渗透测试者了解攻击是为了更好地防御。从蓝队或系统管理员的角度如何防范“土豆”类的本地提权攻击呢遵循最小权限原则这是最根本的。确保服务账户如IIS应用池账户、SQL Server服务账户只拥有其运行所必需的最小权限。如果某个服务不需要SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege就在本地安全策略中将其移除。及时更新系统微软的补丁通常会修复被滥用的COM组件。保持操作系统和所有软件的最新状态能有效封堵大部分已知的CLSID利用途径。启用Windows Defender攻击面减少ASR规则其中有一条规则“阻止Windows本地安全机构子系统lsass被盗用凭据”和“阻止从Windows本地安全机构子系统窃取凭据”可以防范一些凭据窃取行为。更相关的“阻止滥用易受攻击的驱动程序”和“阻止进程创建”等规则如果配置得当可以拦截此类提权行为。部署端点检测与响应EDR现代EDR能够检测可疑的进程创建行为如从IIS工作进程突然创建cmd.exe、令牌模拟操作以及异常的本地网络连接如进程监听非常用端口并及时告警或阻断。应用程序控制使用Windows Defender应用程序控制WDAC或AppLocker限制只有授权的应用程序可以在服务器上运行。这样可以阻止攻击者上传和运行rottenpotato.exe这类未知工具。网络分段与主机防火墙虽然此类攻击主要发生在本地回环但严格的主机防火墙策略可以限制不必要的出站连接增加攻击者横向移动的难度。审计与监控启用详细的进程创建审计4688事件和特权使用审计并集中收集日志。通过SIEM分析异常模式例如一个通常运行ASP.NET的w3wp.exe进程突然创建了cmd.exe或powershell.exe就是一个高危信号。说到底Rotten Potato这类工具之所以能成功根本原因在于Windows庞大而复杂的历史组件架构以及默认配置下赋予服务账户的过高权限。作为攻击方我们需要深入理解其原理灵活测试作为防御方则需要收紧权限、及时更新、加强监控构建纵深防御体系。