CTF Walkthroughs, Hack The Box

Hack The Box – TheNotebook Walkthrough

Introduction

This was an intermediate Linux machine that required hijacking a user session by abusing the “kid” JWT token parameter to gain initial access and exploiting a vulnerability in Docker to escape the container and obtain root privileges.

Enumeration

The first thing to do is to run a TCP Nmap scan against the 1000 most common ports, and using the following flags:

  • -sC to run default scripts
  • -sV to enumerate applications versions

The scan has identified two open ports: port 22 (SSH) and port 80 (HTTP).

Enumerating HTTP

When accessing the site through a web browser, the following page is displayed:

Registering a new “admin” user:

It appears this user already exists, which gives a hint as to what user may need to be compromised later on:

Registering with an “administrator” user instead:

Authenticating as the newly created administrator user:

The next step is to run a scan to find hidden files or directories using Gobuster, with the following flags:

  • dir to specify the scan should be done against directories and files
  • -u to specify the target URL
  • -w to specify the word list to use
  • -x to specify the extensions to enumerate
  • -t to specify the number of concurrent threads

The scan has revealed an “/admin” entry, although this is not allowed for the current user, meaning escalating to the admin user is probably the next step forward.

The site seems to have produced an “auth” JWT token upon signing in:

When unpacking it on jwt.io, it appears there is an “admin_cap” attribute which is currently set to false:

This will probably need to be set to true in order to be able to access the admin page.

Hijacking Admin Session

As part of the parameters contained in the JWT token, there was “kid”, which is an optional header claim which holds a key identifier, which is used to specify the private key the server will use to verify the signature.

It looks like currently, it is pointing to port 7070 on the remote host, which isn’t reachable externally. In order to exploit this, it could be changed to a private key hosted on the attacker machine. Generating a pair of RSA keys:

ssh-keygen -t rsa -b 4096 -m PEM -f stef

Adding the contents of the public and private keys to sign the token and replacing the kid parameter with the key hosted locally. Also changing the admin_cap parameter to true:

Setting up a Python Simple HTTP Server in order to host the private key:

Replacing the JWT token with the one generated by jwt.io:

Refreshing the page – the “Admin Panel” button is now available:

The private key was requested by the server when refreshing the page, as expected:

Exploiting File Upload

When accessing the admin page, there are two buttons available:

When viewing the existing notes, there is a mention to fix config:

When navigating to the note, it mentions that an issue needs where PHP files can be executed to be fixed:

Copying the Laudanum PHP Reverse Shell to the current directory and changing the IP address and port:

Navigating to the file upload functionality and selecting the PHP reverse shell:

The file was uploaded, the file name has been changed, probably through hashsum:

The next step is to set up a Netcat listener, which will catch the reverse shell when it is executed by the victim host, using the following flags:

  • -l to listen for incoming connections
  • -v for verbose output
  • -n to skip the DNS lookup
  • -p to specify the port to listen on

Navigating to the reverse shell through a browser to execute it remotely:

A reverse shell as the www-data user was received:

The following steps can be done to obtain an interactive shell:

  • Running “python3 -c ‘import pty; pty.spawn(“/bin/sh”)’” on the victim host
  • Hitting CTRL+Z to background the process and go back to the local host
  • Running “stty raw -echo” on the local host
  • Hitting “fg + ENTER” to go back to the reverse shell
  • export TERM=linux

The /var/backups/ folder seems to contain a compressed version of the home directory:

Copying the archive to /tmp, decompressing it using tar and using the SSH key for the “noah” user found within it to authenticate via SSH:

cp home.tar.gz /tmp
cd /tmp
tar -zxvf home.tar.gz
ssh -i /home/noah/.ssh/id_rsa noah@localhost

Privilege Escalation

When executing sudo -l, it appears the current user can execute the following command as root:

 /usr/bin/docker exec -it webapp-dev01*

When executing it, it seems to require a command, when providing “ls” it seems to execute it as expected:

When executing bash, a root-level shell is provided, although this appears to be in a Docker container:

Using SearchSploit to find known vulnerabilities in Docker, there appears to be a couple that would allow escaping the container:

Checking the current Docker version, it appears to match the vulnerable one:

This vulnerability in Docker allows attackers to overwrite the host runc binary (and consequently obtain host root access) by leveraging the ability to execute a command as root within one of these types of containers: (1) a new container with an attacker-controlled image, or (2) an existing container, to which the attacker previously had write access, that can be attached with docker exec (which is the current scenario). This occurs because of file-descriptor mishandling, related to /proc/self/exe.

The exploits from ExploitDB did not work, so searching for one from GitHub:

Compiling the binary using go and setting up a Python Simple HTTP Server to host it:

Transferring the binary over to the target machine using Wget:

The next step is to set up a Netcat listener, which will catch the reverse shell when it is executed by the victim host, using the following flags:

  • -l to listen for incoming connections
  • -v for verbose output
  • -n to skip the DNS lookup
  • -p to specify the port to listen on

Assigning to the file execute permission and executing it. On a separate shell, /bin/sh needs to be run using Docker’s exec function, as soon as the exploit runs:

This has finally provided with root-level access to the target machine.

Conclusion

This was a really cool machine, JWT tokens can be very tricky to test, especially without having access to the application’s source code, so it was very interesting to exploit them in an actual lab. The docker escape process was also new to me, as it wasn’t using one of the usual techniques but a vulnerability with Docker itself.