Skip to main content

Starting the box


Link to the box: https://app.hackthebox.com/machines/DarkCorp.

Port Scan

We start off the box by running a port scan on the provided IP.
Attacker Linux
Output of Nmap:
Terminal Output
A few key notes:
  • Port 22 (SSH) is open running OpenSSH 9.2p1 on Debian
  • Port 80 (Web Server) is open running nginx 1.22.1
  • The HTTP title indicates “DripMail” - likely an email service
  • The underlying OS is Linux (Debian)

Edit the Hosts file

As always, we edit the /etc/hosts file to add the hostname:
Attacker Linux
/etc/hosts

Initial Foothold

Enumerating Port 80: Web Server (drip.htb)

Let’s check out the web server at http://drip.htb:

Subdomain Enumeration

We’ll enumerate subdomains to find additional targets:
Attacker Linux
Terminal Output
  • Nice. We found a new target: mail.drip.htb
  • Remember to add this into our hosts file
Let’s add it to our hosts file:
/etc/hosts

Manual Enumeration

We can sign up for an account at http://drip.htb/register:
Credentials
After registering, we are redirected to http://mail.drip.htb, and there is a welcome email:
Terminal Output
Checking the mail service information:
Terminal Output
  • The service is running Roundcube Webmail 1.6.7
  • This version is potentially vulnerable to CVE-2024-42009
Upon checking our mailbox, we saw this interesting message:
Terminal Output

RoundCube XSS (CVE-2024-42009)

Researching the vulnerability: The vulnerability exploits a regex pattern used to remove bgcolor from the body tag:
Vulnerable Regex
  • This regex removes any bgcolor alongside some optional quotation marks anywhere within the body tag
  • We can trick the regex into breaking other attributes
We can use this payload to trigger XSS:
  • The regex removes bgcolor=foo", causing the syntax to break and allowing our onanimationstart handler to execute
The payload should be sent via the contact section at http://drip.htb/index#contact:
HTTP Request
  • The content=html parameter is crucial for the payload to work
  • Success! The XSS triggers when the recipient opens the email

Stealing bcase’s Email

Let’s craft a payload to steal emails from [email protected]. First, we’ll test with a simple fetch:
  • Note: We need to use single quotes inside the onanimationstart handler to avoid breaking the syntax
After testing various payloads, we found this working payload that exfiltrates email content:
Setting up our listener:
Sending the payload to [email protected]:
HTTP Request
Successfully received bcase’s email:
Terminal Output
  • New domain discovered: dev-a3f1-01.drip.htb
  • We need to reset bcase’s password to access the dashboard
We can also steal the password reset token from bcase’s mailbox by targeting a different email UID. The reset token email contains:
Terminal Output
  • We can now reset bcase’s password and access the dashboard

Discovering the Development Dashboard

Additional Hostname Enumeration

Let’s take a step back. We noticed that we haven’t added darkcorp as a domain to our hosts file yet. This is important for CTF boxes:
Attacker Linux
/etc/hosts
Now let’s enumerate subdomains for darkcorp.htb:
Attacker Linux
  • No additional subdomains found

Directory Enumeration on darkcorp.htb

Let’s run directory enumeration on darkcorp.htb:
Attacker Linux
Terminal Output
  • We found a /dashboard directory with multiple subdirectories
  • The structure suggests this is a Flask application
  • /authentication looks particularly interesting
Let’s enumerate with dirsearch to find configuration files:
Attacker Linux
Terminal Output
  • We found a .env file! This typically stores environmental variables and credentials
Downloading the .env file:
/dashboard/.env
  • PostgreSQL database credentials: dripmail_dba:2Qa2SsBkQvsc
  • Flask secret key: GCqtvsJtexx5B7xHNVxVj0y2X0m10jq
  • This is valuable information for later exploitation
Since we know this is a Flask application, let’s enumerate the authentication directory for Python files:
Attacker Linux
Terminal Output
  • We can read the Flask application source code!
In routes.py, we found the password reset functionality:
  • This confirms the dev-a3f1-01.drip.htb domain we found earlier

Accessing the Dashboard

After resetting bcase’s password using the stolen reset token, we can log into the dashboard at http://dev-a3f1-01.drip.htb:
Terminal Output
  • We can see user information including IP addresses
  • The test user has a different IP: 172.16.20.1 - suggesting an internal network

Exploiting SQLi in dev-a3f1-01.drip.htb

The dashboard has a search function that returns interesting error messages:
Terminal Output
  • The error reveals we’re dealing with PostgreSQL via SQLAlchemy
  • The application uses psycopg2 for database connections
Testing the search function, we find that searching for 'bcase' (with quotes) returns results. This suggests SQL injection:
Attacker Linux
  • This returns all users, confirming SQL injection
Some keywords like UNION appear to be filtered. Let’s enumerate the database manually using Stacked Queries:
SQL Injection Payload
  • Tables found: Users, Admins
SQL Injection Payload
  • Columns: id, username, password, email
Dumping user credentials:
SQL Injection Payload
Terminal Output
  • We found password hashes for multiple users
  • ebelford is particularly interesting as it appeared in the user list

PostgreSQL File Read and RCE

Since we have SQL injection in PostgreSQL, we can leverage powerful built-in functions. Let’s test file reading:
SQL Injection Payload
Terminal Output
  • File read works! We can see bcase and ebelford are system users
We can also list directories:
SQL Injection Payload
Terminal Output
Now let’s escalate to RCE. The COPY command can execute system commands, but it appears to be filtered by WAF. We can bypass this using obfuscation:
SQL Injection Payload
  • This stores C O P Y and the command into variable c, then executes it
  • The WAF cannot detect the keyword because it’s obfuscated using CHR() functions
Setting up our listener:
Attacker Linux
Executing the payload:
Terminal Output
  • Success! We have a shell as the postgres user

Pivoting to ebelford

Enumerating the System

Let’s check the hosts file for network information:
Terminal Output
  • We’re on 172.16.20.3 (drip.darkcorp.htb)
  • There’s a domain controller at 172.16.20.1 (DC-01.darkcorp.htb)
  • This indicates an Active Directory environment
Checking our network interfaces:
Terminal Output
  • Confirmed: we’re on the 172.16.20.0/24 network

Finding Credentials in Database Logs

Since we’re running as the postgres user, we should check PostgreSQL logs for sensitive information. LinPEAS might not catch these:
Victim Linux
Terminal Output
  • We found ebelford’s password hash being updated in the logs!
  • Hash: 8bbd7f88841b4223ae63c8848969be86
Cracking the hash:
Attacker Linux
Terminal Output
  • Successfully cracked: ThePlague61780

Alternative Path - PostgreSQL Backups

There’s also an alternative way to find credentials. Someone hinted that credentials exist in /var/backups/postgres:
Victim Linux
Terminal Output
  • We found an encrypted GPG file
Attempting to decrypt:
Victim Linux
  • It requires a passphrase
Trying the database password:
Terminal Output
  • Success! The backup decrypts
Contents of the backup:
Terminal Output
  • We found another user: victor.r with hash cac1c7b0e7008d67b6db40c03e76b9c0
  • This is likely a Windows domain user
Cracking victor.r’s hash:
Attacker Linux
Terminal Output
  • Successfully cracked: victor1gustavo@#

SSH Access as ebelford

Let’s SSH as ebelford:
Attacker Linux
Credentials
  • Successfully authenticated!

Enumerating the Internal Network

Setting up for Lateral Movement

Since we need to access the internal 172.16.20.0/24 network, we’ll set up Ligolo for pivoting. First, download the Ligolo agent to the compromised host:
Victim Linux (ebelford)
Start the Ligolo agent:
Victim Linux (ebelford)
On our attacker machine, start the Ligolo proxy and add a route to the internal network:
Attacker Linux
  • Ligolo creates a tunnel allowing us to access the internal network directly
Alternatively, we can use SSHuttle for easier network access:
Attacker Linux
Credentials
  • This creates a VPN-like tunnel to the internal network without needing to upload additional binaries

Network Discovery

Let’s scan the internal network for SMB hosts:
Attacker Linux
Terminal Output
  • DC-01: Domain Controller at 172.16.20.1 (SMB signing enabled)
  • WEB-01: Web server at 172.16.20.2 (SMB signing disabled - potential relay target!)
Testing our credentials against the domain:
Attacker Linux
Terminal Output
  • Success! victor.r is a valid domain account
Enumerating domain users:
Attacker Linux
Terminal Output
  • Multiple administrative accounts with .adm suffix
  • svc_acc - likely a service account
Checking for AS-REP roastable accounts:
Attacker Linux
  • No AS-REP roastable accounts found

Bloodhound Enumeration

Let’s run Bloodhound to map the Active Directory environment. Unfortunately, Ligolo has DNS resolution issues with Bloodhound, so we’ll use SSH dynamic port forwarding with proxychains instead. Setting up SSH dynamic port forwarding:
Attacker Linux
Credentials
Edit the proxychains configuration:
Attacker Linux
/etc/proxychains4.conf
  • The dnat line ensures traffic to 10.10.11.54 is routed to the actual DC at 172.16.20.1
Now run Bloodhound through proxychains with the --dns-tcp flag:
Attacker Linux
Key findings from Bloodhound:
  • taylor.b.adm is a GPO manager and can PSRemote
  • svc_acc has DNSAdmin privileges

Enumerating SMB Shares

Attacker Linux
Terminal Output
  • We have access to CertEnroll - this suggests ADCS (Active Directory Certificate Services) is in use
Checking for ADCS:
Attacker Linux
Terminal Output
  • ADCS is present but looks complex to exploit

Enumerating WEB-01

Let’s scan WEB-01 for additional services:
Attacker Linux
Terminal Output
  • Port 5000 is running IIS with NTLM authentication
  • Port 5985 (WinRM) is open for PSRemoting

NTLM Relay Attack

Web Dashboard SSRF

Let’s try accessing port 5000 with NTLM authentication:
Attacker Linux
  • This works! The browser login wasn’t working due to Burp Proxy intercepting the NTLM authentication
Examining the HTML source:
  • There’s a “Check Status” functionality that looks interesting
Testing the status check endpoint:
HTTP Request
HTTP Response
  • The application performs health checks on arbitrary hosts!
  • This is an SSRF vulnerability
Testing other ports:
Attacker Linux
Terminal Output
  • Detailed error messages reveal this is a Python application using urllib3
  • When the application connects to an HTTP endpoint, it will authenticate using NTLM
  • We can relay this authentication!

Relaying to Domain Controller

Since we’re on the drip.darkcorp.htb host (172.16.20.3), we can make the application connect back to us and relay the authentication to the Domain Controller. First, let’s update our hosts file on the DC:
Attacker Linux
/etc/hosts
Setting up ntlmrelayx with multiple targets:
targets.txt
Attacker Linux
  • The -w flag starts a web server to capture the authentication
  • --output-file will capture hashes for logging
Now we need to make WEB-01 connect to our machine. Since we’re on drip.darkcorp.htb, we can set up a listener: From our ebelford SSH session on drip.darkcorp.htb:
Victim Linux
Wait, we need to forward this properly. Let’s use a better approach - we’ll start a simple HTTP server on our attacker machine and use SSH port forwarding: Actually, let’s set up the relay differently. We’ll trigger the SSRF to connect to drip.darkcorp.htb (which we control via SSH), and from there relay to the DC:
Attacker Linux
On drip, we set up an HTTP server that will be accessed:
Victim Linux (via SSH)
Now trigger the SSRF:
Attacker Linux
Wait, this won’t work correctly because we need to relay from our attacker box. Let me reconsider the setup. Actually, we need to use SSH port forwarding to relay traffic. On our SSH connection to drip:
Attacker Linux
This forwards port 8081 on drip to port 80 on our attacker machine. Now we start ntlmrelayx:
Attacker Linux
And trigger the SSRF to connect to drip:8081:
Attacker Linux
Terminal Output
  • Success! We relayed svc_acc’s authentication to the LDAP server
  • We now have an interactive LDAP shell as svc_acc
Connecting to the LDAP shell:
Attacker Linux
Terminal Output
  • We have an LDAP shell, but it’s limited in functionality
  • The relay was successful, proving we can abuse the SSRF

Privilege Escalation

Abusing GPO as taylor.b.adm

Finding taylor.b.adm Credentials

From our Bloodhound analysis, we know that taylor.b.adm is a GPO manager with PSRemote capabilities. Let’s try to find credentials for this account. Since direct ADCS exploitation looks complex, let’s try password spraying:
Attacker Linux
Terminal Output
  • Success! Credentials: taylor.b.adm:!QAZzaq1

WinRM Access

Let’s connect via WinRM:
Attacker Linux
  • Successfully connected to the Domain Controller!

GPO Abuse

Since taylor.b.adm is a GPO manager, we can abuse Group Policy to escalate privileges. We’ll use pygpoabuse to create a scheduled task that adds a new admin user. First, identify the GPO we can modify. From Bloodhound or by listing GPOs:
Victim Windows (DC-01)
The GPO path format is:
Terminal Output
  • The GPO ID is: 652CAE9A-4BB7-49F2-9E52-3361F33CE786
Using pygpoabuse on our attacker machine:
Attacker Linux
Terminal Output
  • The tool created a scheduled task via GPO that will add a backdoor user
Forcing a GPO update on the DC:
Victim Windows (DC-01)
Checking for new users:
Victim Windows (DC-01)
Terminal Output
  • New user john has been created!
  • Default credentials from pygpoabuse: john:H4x00r123..
Verifying the account has admin access:
Attacker Linux
Terminal Output
  • Confirmed! john has administrative privileges

Dumping Domain Secrets

Now we can dump the domain secrets:
Attacker Linux
Terminal Output
  • Administrator NTLM hash: fcb3ca5a19a1ccf2d14c13e8b64cde0f

Getting the Flags

User flag from WEB-01:
Attacker Linux
Terminal Output
Root flag from DC-01:
Attacker Linux
Victim Windows (DC-01)
Terminal Output
  • Box complete!

Learning

1. CVE-2024-42009 - RoundCube XSS via Regex Desanitization

A Cross-Site Scripting vulnerability in Roundcube Webmail 1.6.7 allows attackers to steal emails by exploiting a regex pattern that removes bgcolor attributes. By crafting payloads like <body title="bgcolor=foo" name="bar onload=...">, the regex incorrectly removes bgcolor=foo", breaking the syntax and allowing JavaScript execution. This can be used to exfiltrate emails from targets who open malicious messages.

2. Always Enumerate All Domains Thoroughly

Don’t forget to add the box name as a domain in your hosts file (e.g., darkcorp.htb in addition to drip.htb). Different domains may expose different applications and attack surfaces. Always perform both subdomain enumeration and directory busting on all discovered domains.

3. PostgreSQL Arbitrary File Read and RCE via SQL Injection

When you have SQL injection in PostgreSQL, you can leverage powerful built-in functions:
  • pg_read_file('/path/to/file', offset, length) - Read arbitrary files
  • pg_ls_dir('/path/') - List directory contents
  • COPY (SELECT ...) TO PROGRAM 'command' - Execute system commands
If WAF blocks the COPY keyword, bypass it using character concatenation:

4. Check Database Logs and Backup Files When Running as Database User

When you compromise a database service account (like postgres), always check:
  • Database logs: /var/log/postgresql/ - May contain cleartext credentials from UPDATE/INSERT statements
  • Backup files: /var/backups/postgres/ - May contain GPG-encrypted database dumps
  • Configuration files: May contain passwords for decrypting backups
LinPEAS may not catch these files, so manual enumeration is crucial.

5. Pivoting Tools for Internal Networks - Ligolo, SSHuttle, and Proxychains

When you need to access internal networks through a compromised host, use Ligolo for efficient tunneling:
If Ligolo is not available or suitable, use SSHuttle for VPN-like access:
For tools with DNS issues (like Bloodhound with Ligolo), fall back to SSH dynamic port forwarding with proxychains:
Then configure /etc/proxychains4.conf:
The dnat line is crucial for routing traffic to the correct internal host. Use proxychains4 to run tools through the tunnel.

6. NTLM Relay via SSRF

When you find an SSRF vulnerability in a Windows application that performs HTTP requests, the application may authenticate using NTLM. You can relay this authentication to other services:
  1. Set up impacket-ntlmrelayx targeting LDAP or SMB on the Domain Controller
  2. Use SSH port forwarding to make your relay server accessible from the internal network
  3. Trigger the SSRF to connect to your relay server
  4. Capture and relay the authentication to escalate privileges
Note: SMB signing must be disabled on the target for SMB relay, but LDAP relay works regardless.

7. GPO Abuse for Privilege Escalation

Users with WriteProperty, WriteDacl, or GenericAll permissions on Group Policy Objects can abuse GPOs to gain Domain Admin:
  1. Identify the target GPO ID from the SYSVOL path: \\domain\SYSVOL\domain\POLICIES\{GPO-ID}
  2. Use tools like pygpoabuse.py to add a scheduled task via GPO:
  1. Force a GPO update: gpupdate /force
  2. The tool creates a backdoor admin user (john:H4x00r123.. by default)
  3. Use the new admin account to dump domain secrets

Tags

Initial Access

#CVE-2024-42009 #XSS #RoundCube #EmailStealing #SSRF #SQLInjection #PostgreSQL #FileRead #RCE #WAFBypass #CharcterObfuscation #DatabaseLogs #BackupFiles #GPGDecryption

Privilege Escalation

#ActiveDirectory #Bloodhound #Ligolo #SSHuttle #SSHPortForwarding #Proxychains #NTLMRelay #LDAPRelay #Kerbrute #PasswordSpraying #GPOAbuse #ScheduledTask #Secretsdump
Last modified on February 18, 2026