Joe1sn's Cabinet

【内网】从PoC看JuicyPotato提权

从此认识到自己不是做win安全的料

个人认为JuictPotato的前身是著名的Rotten Potato

image-20211022212121001

  1. 使用CoGetInstanceFromIStorage API 调用欺骗RPC,对代理进行身份验证.在此调用中指定了代理 IP/端口
  2. RPC 向代理发送 NTLM 协商包
  3. 代理依赖的NTLM协商到RPC在端口135,被用作模板。同时,执行对AcceptSecurityContext的调用以强制进行本地身份验证
    注:此包被修改为强制本地身份验证.
  4. & 5. RPC 135和AcceptSecurityContext用NTLM Challenge回复
  5. 将两个数据包的内容混合以匹配本地协商并转发到RPC
  6. RPC使用发送到AcceptSecurityContext(8.)的NLTM Auth包进行响应,并执行模拟
  1. 【PotatoAPI】创建COM监听器startCOMListenerThread

    • 初始化WinSocket,创建非阻塞式socket,并监听-t端口。跳转到2,后面的就是监听循环中的

    • 【LocalNegotiator】使用processNtlmBytes处理返回地NTLM信息。处理顺序刚好是1,2,3

      • 首先获取安全主体的预先存在的凭据的句柄,初始化Client和Sever的Token,建立安全上下文(新进程的身份验证),转发给RPC
      • RPC返回NTLM挑战应答问题,新进程的身份验证也会返回他的NTLM挑战应答问题,然后改装RPC的数据,塞入新进程的身份验证的NTLM挑战应答的部分数据
      • 从系统回答中,创建新的system令牌
  2. 【PotatoAPI】同本地135端口建立RPC连接,发送消息从PotatoAPI->rpcSendQ走出队列

  3. 【PotatoAPI】触发triggerDCOM

    • StgCreateDocfileOnILockBytes:创建Istorage对象
    • 【IStorageTrigger】创建IStorageTrigger对象
    • CLSIDFromString:将CLSID字符转为COM对象
    • CoGetInstanceFromIStorage :创建一个新的 对象,使用 IPersistFile::Load初始化
    • 触发DCOM后,进入1中的监听循环
  4. 通过得到的system token,经典的CreateProcessWithTokenW创建新的进程

要一个人写的话工作量还是挺大的,而且IstroageTrigger得自己构造,感谢开源PoC!

参考

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

https://forum.butian.net/share/860