In this post I will be sharing my writeup for HTB-Unicode, which was medium rated box, starting with nmap scan there were only 2 ports ssh and http, on the web server there was a template being used on which we can create an account and get a JWT
token also the site had a parameter to redirect to a url. Analyzing the token it had JKU
which had a url for the JSON encoded public keys which we can take advantage of as we can generate our own set of keys and and host them on our machine and with the use redirect parameter we can make a request to this public key with the help of nginx alias. After becoming admin on the site there was a parameter which was vulnerable to LFI but with unicode characters and with that we were able to access nginx config to find the path where the site is hosted and also a file having the credentials giving us access to code
user. This user was able to run a custom binary treport
as root user which was a python byte compiled file, after de compiling pyinstxtractor
, it was using curl
command giving us the ability to read any file through the config file parameter.
NMAP
Host is up (0.12s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: E06EE2ACCCCCD12A0FD09983B44FE9D9
|_http-generator: Hugo 0.83.1
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Hackmedia
|_http-trane-info: Problem with XML parsing of /evox/about
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
PORT 80 (HTTP)
We get a static bootstrap template on the web server where it has a register and login page so first let’s try to do a simple sqli on login page
And it didn’t work , I tried to explore the page and noticed that when we hover over the Google about us
button it shows a route that uses a GET parameter to go to a url
So let’s just register a user and see what we can further enumerate
We logged in with the user but there wasn’t anything interesting
But one thing to note that this application uses JWT tokens for authentication
It has a jku
which holds the public key for JWT
So I searched for abusing jku in jwt and found an article explaining how we can actually do it , and according to the article we need to generate a public-private 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
We have the private and public key , paste them into the jwt so that we can have a signature verified
Foothold
Now we need to create a jwks.json
file from our key but that will be created in hex format so we'll need to convert it to base64 url encoded form and replace them in the server's jwks.json and host it , then using nginx alias mis-configuration we can make a request through /static../redirect/?url=http://ip/jwks.json
import base64
from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.PublicKey import RSAfp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()e = base64.b64encode(long_to_bytes(key.e)).decode()
n = base64.b64encode(long_to_bytes(key.n)).decode()print("e :" +e+ "\n")
print("n :" +n)
After replacing the jwt token we will be able to access admin dashboard
Here we can see a option to see reports which accepts a GET parameter and expects a file name
On doing ../etc/passwd
, trying to use a lot of ../
but I had no luck in doing LFI here , so searched around for for LFI unicode bypasses and found a blog related to this
With this we were able to read /etc/passwd
file so next we know there's nginx running , we could try to access logs , error logs or vhost config file. I tried to read logs but wasn't able to but was able to read the vhost config file which is /etc/nginx/sites-available/default
This shows us a file db.yaml
which seems to have a password
Since code
is a user on the machine we can try to see if this is his password
Privilege Escalation
Doing sudo -l
we can see that this user can run a custom binary called treport
This gives us 4 options
I tried to do some command injection but it was blocked
So I started to tinker with the binary , trying to see what’s the source code of it , so after running strings
it showed that it has some python libraries meaning that this is a python compiled binary
So let’s transfer this on to our machine and de compile it to get the source code
Using pyinstxtractor
we can get python byte file which can then further convert it into source
https://github.com/extremecoders-re/pyinstxtractor
Then using pycdc
we can convert python byte file to source code, we could have used decompyle3
or uncomplye6
but those only support python 3.0 to 3.7 and this file used python 3.8
We can see the source code that why our input was being blocked , when we were trying command injection
Here it’s using curl
download a file and executing it through system
function to execute it as a command on terminal , although special characters are blocked , but we can still use python3's format string to specify arguments to curl
using -K
to use a config file but instead we can read any file we want from this as it will generate an error that it isn't in a proper format , usually config file would contain headers like this
We can also read root’s ssh key but due to a lot of errors generated while reading it I wasn’t able to use the private key but we can read any file we want.
References
- https://blog.pentesteracademy.com/hacking-jwt-tokens-jku-claim-misuse-2e732109ac1c
- https://linux.die.net/man/1/curl
- https://stackoverflow.com/questions/27127195/how-do-i-set-a-custom-header-in-a-curl-config-file
- https://jlajara.gitlab.io/web/2020/02/19/Bypass_WAF_Unicode.html
- https://github.com/extremecoders-re/pyinstxtractor
- https://github.com/zrax/pycdc