Beyond


This is the beyond page that an additional post enumeration and assessment are conducted as the root user after compromising the target system.

Cron


root@download:~# crontab -l
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command

Surprisingly, the crontab of the root user is empty

Service


root@download:~# ll /etc/systemd/system/
total 80
drwxr-xr-x 18 root root 4096 jul 19 16:06  ./
drwxr-xr-x  5 root root 4096 jul 19 15:35  ../
drwxr-xr-x  2 root root 4096 jul 19 15:35  cloud-init.target.wants/
lrwxrwxrwx  1 root root   40 jul 19 12:39  dbus-org.freedesktop.ModemManager1.service -> /lib/systemd/system/ModemManager.service
lrwxrwxrwx  1 root root   44 Apr 23  2020  dbus-org.freedesktop.resolve1.service -> /lib/systemd/system/systemd-resolved.service
lrwxrwxrwx  1 root root   36 apr 20 14:57  dbus-org.freedesktop.thermald.service -> /lib/systemd/system/thermald.service
lrwxrwxrwx  1 root root   45 Apr 23  2020  dbus-org.freedesktop.timesync1.service -> /lib/systemd/system/systemd-timesyncd.service
drwxr-xr-x  2 root root 4096 jul 19 15:35  default.target.wants/
-rw-r--r--  1 root root  357 apr 21 15:36  download-site.service
drwxr-xr-x  2 root root 4096 jul 19 15:35  emergency.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35  getty.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35  graphical.target.wants/
lrwxrwxrwx  1 root root   38 Apr 23  2020  iscsi.service -> /lib/systemd/system/open-iscsi.service
-rw-------  1 root root  222 apr 21 14:33  management.service
drwxr-xr-x  2 root root 4096 jul 19 15:35  mdmonitor.service.wants/
lrwxrwxrwx  1 root root   38 Apr 23  2020  multipath-tools.service -> /lib/systemd/system/multipathd.service
drwxr-xr-x  2 root root 4096 jul 19 16:06  multi-user.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35  network-online.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35  open-vm-tools.service.requires/
drwxr-xr-x  2 root root 4096 jul 19 15:35  paths.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35  rescue.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35  sleep.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 16:06  sockets.target.wants/
drwxr-xr-x  2 root root 4096 jul 19 15:35 'sshd-keygen@.service.d'/
lrwxrwxrwx  1 root root   31 apr 20 14:57  sshd.service -> /lib/systemd/system/ssh.service
drwxr-xr-x  2 root root 4096 jul 19 15:35  sysinit.target.wants/
lrwxrwxrwx  1 root root   35 Apr 23  2020  syslog.service -> /lib/systemd/system/rsyslog.service
drwxr-xr-x  2 root root 4096 jul 19 16:06  timers.target.wants/
lrwxrwxrwx  1 root root   41 Apr 23  2020  vmtoolsd.service -> /lib/systemd/system/open-vm-tools.service

Instead, there is a service file that can only be access from the root user, /etc/systemd/system/management.service

root@download:~# cat /etc/systemd/system/management.service 
[Unit]
Description=DBMS Management
After=postgresql.service
 
[Service]
Type=simple
ExecStart=/root/venv/bin/python3 /root/management.py
WorkingDirectory=/root
User=root
Restart=always
 
[Install]
WantedBy=multi-user.target

It executes a Python script; /root/management.py

/root/management.py


root@download:~# cat /root/management.py
import paramiko
import time
import os
 
while True:
    print("Deleting files")
 
    for file_name in os.listdir("/var/lib/postgresql/"):
        if file_name != "12":
            os.remove(os.path.join("/var/lib/postgresql/", file_name))
 
    # This gives people 60 seconds to get their payload within .bashrc
    time.sleep(60)
 
    print("SSHing")
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect("localhost", username="root", password="QzN6j#aP#N6!7knrXkN!B$7kq")
 
    chan = ssh.get_transport().open_session()
    chan.get_pty()
    chan.invoke_shell()
    chan.send(b'/bin/bash -i ./manage-db\n')
    time.sleep(5)
    chan.send(b"psql\n")
    time.sleep(30)
 
    if not chan.closed:
        chan.close()

The Python script performs a number tasks with an interval of 95 seconds;

  • Wipes everything in the /var/lib/postgresql/ directory, except for one named, 12
  • SSH through the localhost address with the hard-coded CLEARTEXT credential; root:QzN6j#aP#N6!7knrXkN!B$7kq
  • Opens up an interactive bash shell session to execute the manage-db file
  • Invokes the psql binary
  • Ensures the SSH channel is closed if not already done

manage-db


root@download:~# cat ./manage-db 
#!/bin/bash -i
 
echo "[*] Checking status of database"
SYSTEMD_PAGER= systemctl status postgresql
 
echo "[*] Checking status of webserver"
SYSTEMD_PAGER= systemctl status download-site
 
echo "[*] Entering postgres user, use 'psql' to enter DB"
su -l postgres

The manage-db file is a Bash script that;

  • calls systemctl status postgresql
  • calls systemctl status download-site
  • switches the current UID to the postgres user with the vulnerable su -l command

Weird linker with psql


root@download:/tmp# sudo -u postgres psql

I thought psql being called with a linker was a strange behavior but it does that by default..