Myles Nieman
← All writeups

Freelancer

Overview

Freelancer is a hard Windows box that chains web exploitation through Active Directory abuse. The freelancer platform has an IDOR in its OTP login URLs: the middle segment is base64-encoded user ID, and swapping it to target a higher-privileged account bypasses authentication. The admin console exposes a SQL terminal backed by MSSQL; after escalating to sa and enabling xp_cmdshell, a Defender-evading shellcode payload (donut + freeze) gives a foothold as sql_svc. A plaintext password in a SQL installation config file is sprayed across the domain and matches mikasa. Her home directory contains a 7-Zip archive that turns out to be a memory image; Volatility finds and dumps lsass, and the hash dump yields lorra199’s credentials. BloodHound shows lorra199 has GenericWrite to a group with the ability to add machines and use RBCD against the DC. A rogue computer account, a resource-based constrained delegation ticket, and S4U2Proxy produce a service ticket for Administrator — domain compromise.

Path: IDOR OTP bypass → admin SQL terminal → MSSQL sa / xp_cmdshellsql_svc shell → password spray → mikasa → memory dump → lorra199 → BloodHound GenericWrite → RBCD → Administrator.

Enumeration

Initial scan confirms a Windows domain controller:

Nmap identifies a Windows DC at freelancer.htb

Port 80 hosts the Freelancer web application. Both employer and freelancer registration are available, with a visible job posting section.

Freelancer web application front page

Foothold — IDOR in OTP Authentication

Account registration

Registering both a freelancer and an employer account. The employer login is blocked with “not approved,” so that path is closed for now.

Employer login rejected — account not approved

Directory busting finds a /accounts/recovery endpoint. Using trivially guessable security answers grants access to the recovery flow:

Password recovery endpoint found via directory brute-force

Recovery answers accepted

IDOR in OTP URLs

Applying for a job surfaces a detail endpoint: http://freelancer.htb/freelancer/details/?freelancer_id=10017. The platform also generates OTP login QR codes with URLs in this format:

http://freelancer.htb/accounts/login/otp/<base64_user_id>/<token>/

Freelancer profile page showing the detail endpoint and IDOR potential

The middle segment is simply the user ID encoded in base64. Decoding MTAwMTY= gives 10016. By enumerating IDs and swapping in a base64-encoded target, it is possible to authenticate as any user:

Decoding the base64 segment reveals the numeric user ID

OTP URL breakdown — the base64 is the user ID, the token is one-time

Targeting the admin account (johnHalond@freelancer.htb) by encoding its ID produces a valid OTP link:

OTP URL crafted for the admin account

Logged in as the admin user

The admin console exposes a SQL terminal:

Admin panel with a live SQL terminal

Privilege Escalation — MSSQL to Shell

Escalating MSSQL privileges

The terminal runs against MSSQL. Hash-stealing via xp_dirtree fails to crack:

Attempting MSSQL hash theft via xp_dirtree

Hash captured but not crackable

Pivoting instead: the current user owns msdb, and chaining it to sa impersonation grants sysadmin rights. Enabling xp_cmdshell then gives OS command execution:

EXEC sp_configure 'Show Advanced Options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;

Confirmed ownership of msdb

Sysadmin privs obtained via impersonation chain

xp_cmdshell enabled — OS command execution confirmed

Bypassing Defender

The box resets periodically, so speed matters. Plain binaries get caught by Defender; the chain is:

  1. donut — converts the Meterpreter binary into position-independent shellcode.
  2. freeze — wraps the shellcode in an obfuscated loader that evades static signatures.

The payload is injected into a running process rather than dropped to disk.

donut installed and ready

freeze installed alongside donut

Generating the Meterpreter payload

Shellcode wrapped through donut

freeze producing the obfuscated loader

Payload staged for delivery via xp_cmdshell

Successful process injection — Meterpreter session opens

A Meterpreter session lands as sql_svc.

User — Password Spray to mikasa

Running winPEAS on the box uncovers a SQL Server installation config file containing a plaintext service password:

winPEAS running on the target

winPEAS output highlighting the SQL config file

C:\Users\sql_svc\Downloads\SQLEXPR-2019_x64_ENU\sql-Configuration.INI
SQLSVCPASSWORD="IL0v3ErenY3ager"

Spraying IL0v3ErenY3ager against domain users:

Password spray — mikasa matches the sql_svc password

mikasa reuses the same password.

Accessing mikasa’s files

RunasCs allows command execution in mikasa’s context without an interactive session:

RunasCs used to execute commands as mikasa

Her home directory contains several files of interest:

mikasa’s home directory

Contents of mikasa’s documents

A 7z archive in mikasa’s home

Archive file details

WSL is installed on the box. The 7-Zip archive is exfiltrated via SMB (SCP and netcat were both unavailable or got caught):

SCP installed but transfer failed

SMB-based exfiltration of the archive

Archive received on the attacker host

Lateral Movement — Memory Analysis for lorra199

The 7-Zip archive turns out to be a memory image. Volatility is used to find and dump lsass:

Volatility pslist identifying the lsass process

Volatility lsass dump in progress

lsass dump saved to disk

Running pypykatz or a similar tool against the dump produces a credential dump:

Raw output from the memory credential dump

After filtering through the output, lorra199’s password is recovered:

freelancer.htb\lorra199:PWN3D#l0rr@Armessa199

lorra199’s credentials recovered from the memory dump

lorra199 can log in via WinRM:

Evil-WinRM session as lorra199

Privilege Escalation — RBCD via BloodHound GenericWrite

BloodHound enumeration

lorra199 is a member of the AD Recycle Bin group. Running BloodHound with her credentials:

BloodHound data collection running as lorra199

BloodHound shows that lorra199’s group has GenericWrite over a group that has the AddComputer right, enabling Resource-Based Constrained Delegation (RBCD) against the DC.

Adding a rogue machine account

With AddComputer rights, a fake machine account is created:

Creating a rogue computer account in the domain

Clock sync and ticket request

Kerberos rejects tickets with time skew. After syncing the clock:

$ rdate -n <dc_ip>

Clock synced to the DC for Kerberos

With the rogue machine account controlling RBCD on the DC, requesting a service ticket for Administrator via S4U2Proxy:

Requesting S4U2Proxy service ticket for Administrator

Service ticket for Administrator obtained

Root

Using the ticket to get a shell as Administrator:

Shell session as Administrator via the RBCD ticket

Root flag captured

Domain compromised.

Takeaways

  • Base64-encoded IDs in OTP URLs are a textbook IDOR surface — any time an opaque token decodes to a predictable integer, enumerating it is worth trying before assuming the auth is solid.
  • MSSQL sa + xp_cmdshell is a full OS command execution primitive, but on a hardened host it needs AV evasion; donut + freeze is a reliable shellcode delivery chain for Defender-enabled environments.
  • RBCD with GenericWrite is a powerful AD escalation path: one group membership that allows adding a machine account is enough to manufacture a domain admin service ticket via S4U2Proxy.