Potato家族本地提权细节
字数 2789 2025-08-25 22:58:40

Windows本地提权技术:Potato家族漏洞分析与利用

1. 概述

Potato家族是一系列Windows本地提权技术,利用Windows令牌模拟机制和COM/DCOM/RPC/NTLM等协议的特性,将服务账户权限提升至SYSTEM级别。这些技术主要针对拥有SeImpersonatePrivilegeSeAssignPrimaryTokenPrivilege权限的账户。

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

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认证
  • 流程:
    1. 传递BITS的CLSID和IStorage对象实例给CoGetInstanceFromIStorage
    2. rpcss激活BITS服务
    3. rpcss的DCOM OXID resolver解析序列化数据中的OBJREF
    4. 向攻击者指定的host:port发起DCE/RPC请求
    5. 进行NTLM认证
    6. 通过SSPI的AcceptSecurityContext进行本地NTLM协商
    7. 获取高权限的impersonation级别token
    8. 通过CreateProcessWithTokenW启动新进程

5.3 PrintSpoofer (PipePotato/BadPotato)

  • 原理:利用打印机组件路径检查的BUG和ImpersonateNamedPipeClientAPI
  • 流程:
    1. 创建命名管道
    2. 调用RpcRemoteFindFirstPrinterChangeNotificationEx触发连接
    3. 利用路径标准化漏洞使服务连接攻击者管道
    4. 调用ImpersonateNamedPipeClient模拟客户端token
    5. 使用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实现流程

  1. 检查并启用SeImpersonatePrivilege
  2. 生成随机UUID作为管道名
  3. 创建命名管道(异步I/O)
  4. 调用ConnectNamedPipe等待客户端连接
  5. 创建新线程调用RpcOpenPrinter连接命名管道
  6. 等待spoolsv连接
  7. 调用ImpersonateNamedPipeClient模拟客户端
  8. 使用CreateProcessAsUserWCreateProcessWithTokenW创建新进程

6.2 JuicyPotato实现流程

  1. 创建COM listener线程处理NTLM认证
  2. 创建RPC connection线程进行中继
  3. 触发DCOM调用
  4. 获取当前进程token并启用所需权限
  5. 通过AcceptSecurityContext进行NTLM协商
  6. 从security context获取token
  7. 复制token
  8. 使用CreateProcessWithTokenWCreateProcessAsUserW创建新进程

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. 防御措施

  1. 限制服务账户权限,遵循最小权限原则
  2. 禁用不必要的SeImpersonatePrivilegeSeAssignPrimaryTokenPrivilege
  3. 启用SMB签名
  4. 限制DCOM访问
  5. 及时安装安全更新
  6. 监控异常进程创建和令牌模拟行为

9. 参考资源

  1. Rotten Potato - Privilege Escalation from Service Accounts to SYSTEM
  2. PrintSpoofer - Abusing Impersonate Privileges
  3. Project Zero Issue #325
  4. No more JuicyPotato? Old story, welcome RoguePotato!
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 3. Windows令牌基础 Windows令牌是描述安全上下文的对象,包含: 用户账户的SID 用户所属组的SIDs 登录会话的登录SID 用户或用户组拥有的权限列表 所有者SID 所有者组的SID 访问控制列表 主令牌/模拟令牌 限制SIDs的可选列表 3.1 模拟等级 Anonymous :无法模拟或识别客户端 Identification :可识别客户端身份和特权,不能模拟 Impersonation :可在本地系统模拟 Delegation :可在远程系统上模拟 4. 关键API函数 4.1 CreateProcessWithTokenW 需要 SeImpersonatePrivilege 特权。 4.2 CreateProcessAsUserW 需要 SeAssignPrimaryTokenPrivilege 特权。 4.3 ImpersonateNamedPipeClient 允许命名管道的服务器端模拟客户端的安全上下文。 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 启动新进程 5.3 PrintSpoofer (PipePotato/BadPotato) 原理:利用打印机组件路径检查的BUG和 ImpersonateNamedPipeClient API 流程: 创建命名管道 调用 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 令牌权限检查与启用 7.2 命名管道创建 7.3 DCOM触发 7.4 NTLM协商 8. 防御措施 限制服务账户权限,遵循最小权限原则 禁用不必要的 SeImpersonatePrivilege 和 SeAssignPrimaryTokenPrivilege 启用SMB签名 限制DCOM访问 及时安装安全更新 监控异常进程创建和令牌模拟行为 9. 参考资源 Rotten Potato - Privilege Escalation from Service Accounts to SYSTEM PrintSpoofer - Abusing Impersonate Privileges Project Zero Issue #325 No more JuicyPotato? Old story, welcome RoguePotato!