Passwords, hashes and Flags will be redacted to encourage you to solve those challenges on your own.
“TheNoteBook” is marked as medium difficulty machine that features nginx server which is hosting a notebook webapp to store notes and view them later in time for registered users. The actual webapp in not on host OS, rather it is running inside a docker container on port 8080 and nginx is serving the webpage over port 80 to HTB users. The webapp is using JSON Web Tokens (JWT) for its users for authorization. These JSON Web Tokens consist of sensitive information encoded with base64 and we can read and manipulate these tokens to get access to webapp admin panel and then get a reverse shell by uploading a PHP file. After initial access we find a backup file which contains ssh_keys for local user. The logged on user has permission to execute docker binary as root using sudo, that we can leverage to escalate our privileges to get root shell.
- Web Enumeration
- Linux Enumeration
- Docker Enumeration
- Attacking JSON Web Tokens
- Escaping Docker Container
Initial Nmap scan reveals SSH (22) and HTTP (80) running on target. BTS, I ran gobuster, checked robots.txt file, basically did every normal enumeration to find extra details, unfortunately there’s nothing that interests us. Let’s visit the HTTP service.
There’s nothing else other than register and login button. Let’s register ourselves and login.
If we visit /notes then we’d see we can add our own notes and save them. At first I tried SSTI, Command injection and couple other attacks but they didn’t work. In gobuster result I found a /admin page, I tried to access but it’s forbidden to us.
So, let’s fire up BurpSuite and intercept.
We got a cookie with authorization token. Looks like base64 encoding. Let’s copy and decode with CyberChef,
I have highlighted readable text for ease. The first output line is header, it is JSON Web Token (JWT), using RSA256 algorithm to sign the data to prevent it from modifying and it’s pointing to Key Identifier (kid) to secure JWS (JSON Web Signature). The second output line is payload which consist of username, email and authorization (permission). The remaining part is signature to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.
The signature is used to verify the message wasn’t changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.
It’s private key is on it’s localhost and it’s being retrieved via HTTP on port 7070. At this moment we don’t have access to that private key, however we can modify the JWT header, payload and sign it with our own signature (RSA pub key).
First we need to create RSA public and private key. It’s possible using openssl or if you don’t want to run command then you can use cryptotools.net
I am comfortable with running commands so I’d use openssl to generate RSA keys.
First I generate private key with name “notebook.key” and second I extract public key and name it “notebook.pub”.
Visit JWT site to modify, encode and sign our token. We need to copy the whole JWT token.
Paste it on JWT.io site.
On your left side it is encoded JWT and on right we have decoded JWT and signature section.
We need to modify header and payload, then we need to add our recently generated public key and private key.
I have added my public and private keys, I have modified payload claim “admin_cap” from ‘0' to ‘1’ (this gives us admin rights) and I have modified header claim “kid” to my local IP address. If everything goes right you’d see “signature verified”. Our JWT encoded token is ready, but now we need to set a HTTP service to serve the private key.
Make sure to start http service where the private key is. Now copy the modified and encoded JWT and paste it in burpsuite and forward it.
Once you forward this token to server, you’d see that you got a hit on your HTTP.
The key has been retrieved by server to verify data. If we check the website, then we’d see the ‘admin panel’ section this time.
Every time we click on admin related sections we have to intercept and modify the JWT token, it’s a bit nuisance. So we will use a “cookie-editor” plugin to use our JWT cookie every time we move around.
Paste JWT cookie and save it. After adding make sure to turn off the burpsuite intercept.
Admin has some notes of his/her own.
If we check the first note, it says “need to fix where php files are being executed”.
So, we can upload our own php webshell and get a reverse shell. You can use PentestMonkey’s php webshell. Change IP:Port, setup netcat listener.
From upload section select webshell and save it.
Now we need to view the file to execute it on server side.
Aight, *hacker voice* we are in. We got our initial access. Now we move to get our first user flag.
Privilege Escalation — User
There’s user named “noah”, we need to get access to his shell. Let’s run LinPeas and get insight.
Two results looks promising. Runc to work we need sudo privileges, perhaps ‘noah’ user can able to take advantage of that. Backup directory a tar file with read attributes to current user (www-data). Let’s copy it to /tmp and extract it.
We got a directory named “noah”. Let’s check the content.
We got ‘noah’ users ssh_keys. Let’s use them to ssh.
We go the user access, let’s read flag.
Privilege Escalation — root
sudo -l reveals that we have permission to run docker binary with command in running container and we also have a container name.
Running docker version is 18.06.0-ce. If we check the vulnerabilities based on that then we’d get two results from searchspolit.
It’s written in golang, so we have to install it on our kali machine. Follow this guide if you want.
Once installed, clone the POC repository to kali and edit main.go accordingly.
Modify highlighted section and add accordingly your payload. I am going to get a reverse shell of root. If you want you can get the root flag or id_rsa key or whatever you like.
Build with go
We got our executable file. Now run http server in same directory to download it on target machine.
Now we need to access the docker container and download the executable file.
Now we need to download and change permission to that file.
Before we execute we need another SSH shell of ‘noah’ user. So login using previously retrieved SSH keys of noah user. Also we need a netcat listener on port which we used inside ‘main.go’ file.
Once you see “[+] Overwritten /bin/sh successfully”, switch to another SSH shell which is running in another tab and run below command.
If you see “No help topic for ‘/bin/sh” then switch to netcat listener.
We got all the flags required to complete this machine.
Thank you for reading this blog. While attempting this challenge I learned so many things. This was unique target with unique vulnerability.