TheNotebook is a medium difficulty machine on HackTheBox created by mostwanted002. For the user part we will exploit a RFI in a JWT-Auth mechanism, allowing us to forge our own certificate to sign any token. This gives us admin access on the website and we can upload a small php web shell. Once on the machine we find the backed up home folder of a user including his ssh key. Logged in as him we can run docker exec on a container with a vulnerable docker version. This let’s us overwrite runc and execute arbitrary commands as root.
User
Nmap
As usual we start our enumeration off with a nmap scan against all ports, followed by a script and version detection scan against the open ones to get a full picture against the attack surface.
All ports scan
1 |
|
Script and version
1 |
|
JWT cert forge
There are only 2 ports open on the machine, with http being the bigger attack surface so we will start there. Opening it up in our browser we see a notebook application.
The application let’s us create a user which we do in the next step.
Looking at the cookies after logging in we see that a JWT is managing our session. A JWT consists of 3 base64 encoded parts. The first part, the header
, contains information about the token type and the signing. The second part contains the payload
which is the data important for session managing in this case. The third part is the signature of the cookie.
When working with JWT’s a usefull website is jwt.io, where we can edit tokens in a nice interface.
Pasting our token there we see it is signed with a certificate which is accessed over http
. Secondly there is a admin_cap
key in the payload
, which has its value set to 0.
We want to set the admin_cap
to 1. To do this we need to sign the token again else it is not valid. Since we don’t have access to the original key we need to generate our own one and try to make it read from us over http.
In a first step we create a private key with openssl
choosing a passphrase of our liking.
1 |
|
Next we generate the corresponding public key entering the passphrase again.
1 |
|
To generate the token and access it later we also generate a private key without the passphrase encryption in the next step.
1 |
|
With everything prepared we can host our newly generated key with a python web server.
1 |
|
Next we swap out the value for the kid
key to point to our hosted private key. Change the admin_cap
to 1 and paste our public and private key(the decrypted one) into the signature fields to sign it.
We can swap the cookie now and reload the page. After it finished loading we see a Admin Panel
, which we did not have access to before and also a hit on our webserver checking our key.
1 |
|
File upload
Looking at the Admin Panel we have 2 new functionalities on the website, View Notes
and Upload File
.
Upload File
sounds very interesting, but let’s look at the notes first to gather more information. The first note mentions a security vulnerability about all php files on the server being executed, which could pair well with the upload functionality.
The second note mentions backups being scheduled which might be interesting for later on.
To abuse the file upload we generate a small and simple php web shell in a first step.
1 |
|
After uploading it it get’s asigned a new name and we can click to view it. Note here that there is a cleanup script running, so if the file is gone one has to reupload it.
We can quickly validate php is really executed by passing the id
command to the cmd
parameter of our web shell.
Since we now have confirmed RCE on the machine we can go for a reverse shell. First we set up our ncat listener, then we intercept the web shell request in Burp, send it to repeater and change the request method. We use a simple bash reverse shell which we URL-encode as the post parameter.
1 |
|
After sending the request we get a shell back on our listener which we upgrade with python and fix the terminal size.
1 |
|
Backup
Backtracking to the earlier found note, checking the /var/backups
directory we see a non default home.tar.gz
archive.
1 |
|
Extracting this it is indeed a backup of the home directory of a user, which even featuers his private ssh key.
1 |
|
Copying the key to a file and setting the right permission on it we can now ssh into the target as noah and grab the user flag.
1 |
|
Root
Checking for sudo permission we can see noah is able to run docker exec -it
on any container starting with webapp-dev01
.
1 |
|
Looking at the docker version it is below 18.09.2
, which means its version of runc might be vulnerable to CVE-2019-5736. To exploit this we can overwrite a binary (/bin/sh in this case) inside the docker container with #!/proc/self/exe
which points to the binary that started the process. With this we can now overwrite the runc binary on the host, giving us command execution as root.
Following this PoC for it we first change the main.go
file to include the command which we want to run, in this case setting the suid bit on bash and compile the file.
main.go
1 |
|
1 |
|
Looking at /bin/bash
it has the normal permissions before performing the exploit.
1 |
|
First we start two parallel ssh sessions on the target to run and trigger the exploit. Now we connect to the docker container as the PoC mentions, download and run our compiled go binary.
1 |
|
On the host we connect to the docker like we did before but this time it obviously does not work because /bin/sh
has been overwritten.
1 |
|
Inside the container we see that it successfully got the file handle…
1 |
|
… and looking on the host again we see that runc was successfully overwritten and our payload was executed.
1 |
|
Now we can just drop into a rootshell and add the flag to our collection.
1 |
|