Potato家族本地提权细节
字数 2789 2025-08-25 22:58:40
Windows本地提权技术:Potato家族漏洞分析与利用
1. 概述
Potato家族是一系列Windows本地提权技术,利用Windows令牌模拟机制和COM/DCOM/RPC/NTLM等协议的特性,将服务账户权限提升至SYSTEM级别。这些技术主要针对拥有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege权限的账户。
2. 前置条件与权限
2.1 所需权限
SeImpersonatePrivilege(模拟客户端权限)SeAssignPrimaryTokenPrivilege(分配主令牌权限)
2.2 默认拥有这些权限的账户
- 本地管理员账户(不包括管理员组普通账户)
- 本地服务账户
- 由SCM启动的服务
- Windows服务的登录账户:
- Local System (
NT AUTHORITY\System):本地系统最高权限 - Network Service (
NT AUTHORITY\Network Service):本地普通用户权限,网络访问时行为类似Local System - Local Service (
NT AUTHORITY\Local Service):本地普通用户权限,始终使用ANONYMOUS LOGON
- Local System (
3. Windows令牌基础
Windows令牌是描述安全上下文的对象,包含:
- 用户账户的SID
- 用户所属组的SIDs
- 登录会话的登录SID
- 用户或用户组拥有的权限列表
- 所有者SID
- 所有者组的SID
- 访问控制列表
- 主令牌/模拟令牌
- 限制SIDs的可选列表
3.1 模拟等级
- Anonymous:无法模拟或识别客户端
- Identification:可识别客户端身份和特权,不能模拟
- Impersonation:可在本地系统模拟
- Delegation:可在远程系统上模拟
4. 关键API函数
4.1 CreateProcessWithTokenW
BOOL WINAPI CreateProcessWithTokenW(
_In_ HANDLE hToken,
_In_ DWORD dwLogonFlags,
_In_opt_ LPCWSTR lpApplicationName,
_Inout_opt_ LPWSTR lpCommandLine,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory,
_In_ LPSTARTUPINFOW lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
需要SeImpersonatePrivilege特权。
4.2 CreateProcessAsUserW
BOOL WINAPI CreateProcessAsUserW(
_In_opt_ HANDLE hToken,
_In_opt_ LPCWSTR lpApplicationName,
_Inout_opt_ LPWSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory,
_In_ LPSTARTUPINFOW lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
需要SeAssignPrimaryTokenPrivilege特权。
4.3 ImpersonateNamedPipeClient
BOOL ImpersonateNamedPipeClient(
HANDLE hNamedPipe
);
允许命名管道的服务器端模拟客户端的安全上下文。
5. Potato家族技术详解
5.1 原始Potato
- 原理:利用WPAD或LLMNR/NBNS投毒,使高权限系统服务请求攻击者监听端口并进行NTLM认证,然后relay到本地SMB listener
- 限制:对有SMB签名的系统无效,微软已通过缓存机制缓解
5.2 RottenPotato & JuicyPotato
- 原理:通过DCOM call使服务向攻击者监听端口发起连接并进行NTLM认证
- 流程:
- 传递BITS的CLSID和IStorage对象实例给
CoGetInstanceFromIStorage - rpcss激活BITS服务
- rpcss的DCOM OXID resolver解析序列化数据中的OBJREF
- 向攻击者指定的host:port发起DCE/RPC请求
- 进行NTLM认证
- 通过SSPI的
AcceptSecurityContext进行本地NTLM协商 - 获取高权限的impersonation级别token
- 通过
CreateProcessWithTokenW启动新进程
- 传递BITS的CLSID和IStorage对象实例给
5.3 PrintSpoofer (PipePotato/BadPotato)
- 原理:利用打印机组件路径检查的BUG和
ImpersonateNamedPipeClientAPI - 流程:
- 创建命名管道
- 调用
RpcRemoteFindFirstPrinterChangeNotificationEx触发连接 - 利用路径标准化漏洞使服务连接攻击者管道
- 调用
ImpersonateNamedPipeClient模拟客户端token - 使用
CreateProcessAsUserW创建新进程
5.4 RoguePotato
- 改进:针对高版本Windows DCOM解析器限制的绕过
- 方法:使用远程主机的135端口做流量转发,将其转回受害者本机端口
- 协议:使用
ncacn_np:localhost/pipe/roguepotato[\pipe\epmapper]让RPCSS连接
5.5 SweetPotato
- 特点:COM/WinRM/Spoolsv的集合版,结合了JuicyPotato和PrintSpoofer的技术
- 当WinRM未启用时,监听5985端口使BITS服务发起NTLM认证
6. 技术实现细节
6.1 PrintSpoofer实现流程
- 检查并启用
SeImpersonatePrivilege - 生成随机UUID作为管道名
- 创建命名管道(异步I/O)
- 调用
ConnectNamedPipe等待客户端连接 - 创建新线程调用
RpcOpenPrinter连接命名管道 - 等待spoolsv连接
- 调用
ImpersonateNamedPipeClient模拟客户端 - 使用
CreateProcessAsUserW或CreateProcessWithTokenW创建新进程
6.2 JuicyPotato实现流程
- 创建COM listener线程处理NTLM认证
- 创建RPC connection线程进行中继
- 触发DCOM调用
- 获取当前进程token并启用所需权限
- 通过
AcceptSecurityContext进行NTLM协商 - 从security context获取token
- 复制token
- 使用
CreateProcessWithTokenW或CreateProcessAsUserW创建新进程
7. 关键代码分析
7.1 令牌权限检查与启用
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken);
GetTokenInformation(hToken, TokenPrivileges, NULL, dwTokenPrivilegesSize, &dwTokenPrivilegesSize);
pTokenPrivileges = (PTOKEN_PRIVILEGES)malloc(dwTokenPrivilegesSize);
GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwTokenPrivilegesSize, &dwTokenPrivilegesSize);
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
7.2 命名管道创建
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
ConvertStringSecurityDescriptorToSecurityDescriptor(L"D:(A;OICI;GA;;;WD)", SDDL_REVISION_1, &((&sa)->lpSecurityDescriptor), NULL);
hPipe = CreateNamedPipe(pwszPipeFullname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, 10, 2048, 2048, 0, &sa);
7.3 DCOM触发
CreateILockBytesOnHGlobal(NULL, true, &lb);
StgCreateDocfileOnILockBytes(lb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
IStorageTrigger* t = new IStorageTrigger(stg);
CLSIDFromString(olestr, &clsid);
CLSIDFromString(OLESTR("{00000000-0000-0000-C000-000000000046}"), &tmp);
CoGetInstanceFromIStorage(NULL, &clsid, NULL, CLSCTX_LOCAL_SERVER, t, 1, qis);
7.4 NTLM协商
AcquireCredentialsHandle(NULL, lpPackageName, SECPKG_CRED_INBOUND, NULL, NULL, 0, NULL, &hCred, &ptsExpiry);
AcceptSecurityContext(&hCred, nullptr, &secClientBufferDesc, ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_CONNECTION, SECURITY_NATIVE_DREP, phContext, &secServerBufferDesc, &fContextAttr, &tsContextExpiry);
QuerySecurityContextToken(test->negotiator->phContext, &elevated_token);
8. 防御措施
- 限制服务账户权限,遵循最小权限原则
- 禁用不必要的
SeImpersonatePrivilege和SeAssignPrimaryTokenPrivilege - 启用SMB签名
- 限制DCOM访问
- 及时安装安全更新
- 监控异常进程创建和令牌模拟行为