Rotten/Juicy Potato提权工原理分析

@TOCRotten/Juicy Potato提权原理分析

Rotten/Juicy Potato提权工原理分析

当 DCOM 对象被传递到进程外 COM 服务器时,对象引用被编组在 OBJREF 流中。对于按引用编组,这会导致生成 OBJREF_STANDARD 流,该流为服务器提供足够的信息以定位原始对象并绑定到它。除了对象的标识还有一个 RPC 绑定字符串列表(包含一个 TowerId 和一个字符串)。当发生解组时,通过将塔指定为 NCACN_IP_TCP 和host[port]形式的字符串,这可以被滥用以连接到任意 TCP 端口。当对象解析器尝试绑定 RPC 端口时,它将与指定地址建立 TCP 连接,并且如果需要,将尝试基于安全绑定进行身份验证。

如果我们在绑定中指定 NTLM 身份验证服务,则身份验证将使用基于 NTLM。我们只需要获得一个特权 COM 服务来解组对象,我们可以通过找到一个合适的 DCOM 调用来接受一个对象。但是我们可以通过滥用激活服务来进行一般的编组IStorage 对象并针对任何系统服务(例如 BITS)执行此操作。所以这给我们带来了一个反射的 NTLM 身份验证带来挑战:

  • 使用 NTLM 反射回本地 SMB 服务(根据 WebDAV 版本)
  • 在本地协商 NTLM,它将返回 LocalSystem 的完整模拟级别令牌(即使作为普通用户完成)。可以将其与 SeImpersonatePrivilege 结合起来进行令牌绑架。
  • 将 NTLM 反射回本地 RPC TCP 端点

Rotten Potato原理

**前提条件:**需要具备 SeImpersonate 或者 SeAssignPrimaryToken 权限来调用 ImpersonateSecurityContext API。

本地 DCOM DCE/RPC 连接可以反射回侦听 TCP 套接字,允许访问 LocalSystem 用户的 NTLM 身份验证消息,可以重放到本地 DCOM 激活服务以提升权限。

Rotten Potato 实现过程(BITS 服务 - RPC):

1)调用 API CoGetInstanceFromIStorage 在本地 6666 端口加载 COM 对象“BITS 服务”(通过指定 CLSID),然后通过将端口 6666 与 135(RPC)之间交换数据包,使得(以 SYSTEM 身份运行)BITS 服务向 RPC135 端口进行 NTLM 身份验证。即欺骗NT AUTHORITY\SYSTEM帐户通过 NTLM 向我们控制的 TCP 端点进行身份验证。

备注:CoGetInstanceFromIStorage 会尝试从 “指定的 host:port” 加载 “指定对象“ 的实例(通过 CLSID 指定对象),BITS 的 CLSID 为 {4991d34b-80a1-4291-83b6-3328366b9097}。

2)攻击者通过一系列 Windows API 调用将此身份验证在本地协商NT AUTHORITY\SYSTEM帐户的安全令牌,将 COM 发送的 Negotiate 消息中的 NTLM 部分提取出来,将其转发至 135 端口(RPC);然后将 RPC 返回的 Challenge 替换为本地协商的数据(替换 NTLM Server Challenge 字段 与 Reserved 字段)后发送给 COM;当 COM 收到处理后的 Challenge 消息后,它将在内存中进行后台身份验证,使用上面调用的结果调用 ImpersonateSecurityContext,以获取模拟令牌

备注:调用 AcceptSecurityContext 函数来接收 Negotiate 消息,并发送 Challenge 消息;并将 Authentiate 消息传递给该函数,以完成身份验证;最后,调用 ImpersonateSecurityContext 函数获得访问令牌。

3)最后调用 CreateProcessWithTokenW 或 CreateProcessAsUserW,以令牌拥有的权限开启进程。

NTLM 中继到本地RPC端口

从本地NT AUTHORITY\SYSTEM帐户NTLM 中继到其他一些系统服务一直是 Potato 提权漏洞的主题。 第一步是诱骗 SYSTEM 帐户对我们控制的某些 TCP 侦听器执行身份验证。欺骗 DCOM/RPC 到 NTLM 向我们进行身份验证。 这种更复杂方法的优点是它 100% 可靠,立即触发,而不是必须等待 Windows 更新。

监听COM服务

我们将滥用对 COM 的 API 调用来启动这一切。 调用是CoGetInstanceFromIStorage

public static void BootstrapComMarshal()
{
IStorage stg = ComUtils.CreateStorage();
 
// Use a known local system service COM server, in this cast BITSv1
Guid clsid = new Guid("4991d34b-80a1-4291-83b6-3328366b9097");
 
TestClass c = new TestClass(stg, String.Format("{0}[{1}]", "127.0.0.1", 6666)); // ip and port
 
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);
}

CoGetInstanceFromIStorage调用尝试从调用者指定的位置获取指定对象的实例。 这里告诉 COM 我们想要一个 BITS 对象的实例,我们想从 127.0.0.1 端口 6666 加载它。它实际上比这更复杂一点,因为我们实际上是从IStorage对象中获取对象,而不仅仅是直接传递host/port。 在上面的代码中,TestClass实际上是一个IStorage对象的实例,我们替换了其中的一些零碎部分以指向127.0.0.1:6666

中间人中继

已经启动了一个本地 TCP 侦听器, COM 试图在端口 6666 上与我们发起交互。 如果我们以正确的方式回复,可以让 COM(以 SYSTEM 帐户运行)尝试与我们执行 NTLM 身份验证。

COM 使用 RPC 协议与我们交互,将我们在 TCP 端口 6666 上从 COM 接收到的任何数据包中继回 TCP 端口 135 上的本地 Windows RPC 侦听器。 然后,我们可以使用从 TCP 135 上的 Windows RPC 收到的这些数据包作为我们对 COM 回复的模板。

在这里插入图片描述

收到的第一个数据包(数据包 #7)是从端口 6666 传入的( COM传来的)。 接下来,将相同的数据包(数据包 #9)中继到 TCP 135 上的 RPC。然后在数据包 #11 中,我们从 RPC(TCP 135)收到回复,在数据包 #13 中,我们将该回复中继到 COM。只需重复此过程,直到进行 NTLM 身份验证。

NTLM 中继和本地令牌协商

本地令牌协商流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aEXdYjx0-1624613487275)(D:\chenyumei360\Potato提权\RottenJuicy Potato提权工具\image-20210625150258589.png)]

左侧蓝色是 COM 在 TCP 端口 6666 上发送给我们的数据包。右侧红色是我们将使用从这些数据包中提取的数据进行 Windows API 调用。 在API 调用中, 为了使用 NTLM 身份验证在本地协商安全令牌,必须首先调用函数AcquireCredentialsHandle来获取我们需要的数据结构的句柄。接下来,我们调用AcceptSecurityContext,该函数的输入将是 NTLM 类型 1(negotiate)消息。 输出将是 NTLM 类型 2(Challenge)消息,该消息被发送回尝试进行身份验证的客户端,在本例中为 DCOM。当客户端以 NTLM 类型 3(Authenticate)消息响应时,我们然后将其传递给对AcceptSecurityContext的第二次调用以完成身份验证过程并获取令牌。

此过程目的是得到NTLM 类型 2(Challenge)消息,后续步骤将用到该数据。

TYPE 1 (NEGOTIATE) PACKET

在 RPC 和 COM 之间中继几个数据包后,最终 COM 将尝试通过发送 NTLM 类型 1(negotiate)消息来尝试向我们发起 NTLM 身份验证,如下面的数据包捕获的数据包 #29 所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7UNf8uvd-1624613487276)(D:\chenyumei360\Potato提权\RottenJuicy Potato提权工具\image-20210625151022104.png)]

同样,我们将其转发给 RPC(在 TCP 135 上),RPC 将回复一个 NTLM Challenge。

此外, 当我们从 COM 收到 NTLM 类型 1(negotiate)消息时,我们截取数据包的 NTLM 部分(如下所示),并使用它开始本地协商令牌的过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijKgfdmG-1624613487278)(D:\chenyumei360\Potato提权\RottenJuicy Potato提权工具\image-20210625151133867.png)]

因此,如上所述,我们调用AcquireCredentialsHandle,然后调用AcceptSecurityContext,将我们从该数据包中提取的 NTLM 类型 1(negotiate)消息作为输入传递。

NTLM TYPE 2 (CHALLENGE) PACKET

TYPE 1 (NEGOTIATE) PACKET我们将 NTLM 类型 1(negotiate)数据包转发到端口 135 上的 RPC,RPC 现在将回复 NTM 类型 2(Challenge)数据包,这可以在上面的数据包 #33 中的数据包捕获中看到。 这一次,不是简单地将这个数据包转发回 COM,我们需要先做一些工作。

捕获的两个 NTLM 类型 2(Challenge)数据包:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QhkegLxJ-1624613487281)(D:\chenyumei360\Potato提权\RottenJuicy Potato提权工具\image-20210625151530008.png)]

请注意突出显示的字段NTLM Server Challenge及其下方的字段Reserved,它们的值不同。 如果简单的将数据包从 RPC(左侧)转发到 COM(右侧),这将没有任何影响。

回想一下,当我们对AcceptSecurityContext进行 Windows API 调用时,该调用的输出是一条 NTLM 类型 2(Challenge)消息。 我们在这里所做的就是:在需要返回给COM 的 NTLM blob中,**用Windows API 调用返回的结果替换RPC返回的NTLM 类型 2(Challenge)。**因为我们需要 COM作为 SYSTEM 帐户运行,使用 NTLM ChallengeReserved部分用来协商本地令牌进行身份验证,如果我们没有替换数据包中的这一部分,那么我们对AcceptSecurityContext的调用将失败。

尝试身份验证的客户端(在本例中为 具有SYSTEM权限的 COM)需要对 NTLM 类型 2(Challenge)数据包的部分NTLM Server ChallengeReserved进行验证,并且只有AcceptSecurityContext调用产生的值,才会获得我们的令牌。

Because we need COM, running as the SYSTEM account to authenticate using the NTLM challenge and “Reserved” section that we are using to negotiate our local token, if we did not replace this section in the packet, then our call to “AcceptSecurityContext” would fail.

We’ll talk more about how local NTLM authentication works later, but for now just know that the client who is trying to authenticate (in this case SYSTEM through COM) needs to do some magic with the “NTLM Server Challenge” and “Reserved” sections of the NTLM Type 2 (Negotiate) packet, and that we’ll only get our token if this magic is performed on the values produced by our call to “AcceptSecurityContext”.

NTLM TYPE 3 (AUTHENTICATE) PACKET

所以现在我们已经将修改后的 NTLM 类型 2(Challenge)数据包转发到 COM,其中ChallengeReserved字段与AcceptSecurityContext的输出相匹配。Reserved字段实际上是一个SecHandle的引用,当SYSTEM账户收到NTLM Type 2消息时,会在内存中进行幕后验证。 这就是为什么我们更新Reserved字段如此重要的原因。否则,它将向 RPC 而不是 US 进行身份验证!

完成此操作后,COM 代表 SYSTEM 帐户将向我们发回 NTLM 类型 3(Authenticate)数据包。 这将是空的(因为这里的所有实际身份验证都发生在内存中),但我们将使用它来对AcceptSecurityContext进行最终调用。

模拟令牌

然后,我们可以使用上述最终调用的结果调用ImpersonateSecurityContext以获取模拟令牌。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ooZiSOj-1624613487282)(D:\chenyumei360\Potato提权\RottenJuicy Potato提权工具\image-20210625153559622.png)]

如果我们想模拟令牌,我们最好以具有 SeImpersonate 权限(或同等权限)的帐户身份运行。 幸运的是,这包括 Windows 中的许多服务帐户,渗透测试人员最终经常使用这些帐户运行。 例如,IIS 和 SQL Server 帐户。

Juicy Potato(指定服务 - RPC)

Juicy Potato 和 Rotten Potato 原理相似,在其基础上进行上改进,可以选择加载其他的服务(通过指定 CLSID),自定义 COM 监听端口,绑定到任意 IP,以及创建进程的方式等等。

参考:Rotten Potato

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值