Sandboxes are only as strong as their implementation. Codify gives you a Node.js code editor to play with - and a vm2 version that plays right back.
Machine info
| Name | Codify |
| Platform | HackTheBox |
| OS | Linux |
| Difficulty | Easy |
TL;DR
- Web app runs Node.js snippets in a vm2 sandbox;
child_processis blocked, but vm2’s context escaping lets you break out entirely - Shell as
svc, linpeas finds a SQLite database with a bcrypt hash forjoshua- cracked with John + rockyou - SSH as joshua,
sudo -lshows/opt/scripts/mysql-backup.shas root; the script uses unquoted[[ $DB_PASS == $USER_PASS ]]enabling glob-based password brute-forcing - Alternatively, compile and run the dirtyfrag LPE directly as
svcand skip joshua entirely
Recon
Nmap
| |

Ports 22 (SSH), 80 (HTTP/Apache), and 3000 (Node.js Express). Port 3000 is the interesting one.
Enumeration
The web app

Codify is a Node.js sandbox - you paste code and it runs in the browser. The site mentions it uses sandboxing technology with some limitations, and links to a “limitations” page. Worth checking what’s blocked.
Trying the obvious route first:
| |

child_process is not allowed. The sandbox is vm2 - a well-known Node.js sandboxing library that has had several CVEs around context escaping.
Foothold
vm2 sandbox escape
The key insight: vm2’s runInNewContext function isolates the code, but earlier versions had a vulnerability where you could walk the prototype chain to reach the process object of the host Node.js runtime. Once you have process, you can require any module - including child_process.
| |
The chain: this inside the context -> .constructor (Object) -> .constructor (Function) -> called with 'return process' to get the host process object -> .mainModule.require('child_process') -> execute a base64-encoded bash reverse shell.

Shell as svc@codify.
Finding the SQLite database
Linpeas flagged the /var/www/contact/ directory:

There’s a tickets.db file in there. Uploaded it to Kali for analysis:

| |

SQLite database. Opened it:

The users table has a bcrypt hash for joshua.
Lateral Move to joshua
Hash cracking
Saved the hash and ran John:



Password: spongebob1.
SSH as joshua

Privilege Escalation
sudo -l
| |

Joshua can run /opt/scripts/mysql-backup.sh as root. Time to read that script.
mysql-backup.sh - glob injection

The script reads a password from the user and checks it like this:
| |
The problem: $USER_PASS is not quoted inside [[ ]]. In bash’s [[ construct, the right-hand side of == is treated as a glob pattern when unquoted. So if you enter *, it matches any string - including the real password.
This means we can brute-force the password character by character: test a*, b*, …, k* until it matches, then test ka*, kb*, and so on. Each successful match tells us the next character. And since the script is calling the mysql binary, we can see the full command (including the password in plaintext) using pspy - but the brute-force approach is more satisfying.
I wrote a bash brute-forcer:
| |

Full password recovered: kljh12k3jhaskjh12kjh3.

Root.
Alternative: dirtyfrag LPE (from svc, no joshua needed)
There’s also a newer kernel LPE - dirtyfrag - that works directly from the svc shell, skipping the whole joshua lateral move:
| |

Root from svc in one step.
Takeaways
- vm2 is not a security boundary. Multiple sandbox escape techniques exist for vm2 - if you see it running user-supplied Node.js, check the version and look for prototype chain escapes.
- Unquoted variables in
[[ ]]are glob patterns.[[ $var == $input ]]without quoting$inputis a classic bash footgun. Any script doing this with a secret comparison is brute-forceable character by character. - SQLite databases in web app directories often hold credentials.
/var/www/is always worth walking when you land on a web server box. - Always check if a public LPE applies before spending time on a long privesc chain. Dirtyfrag, dirty pipe, dirty cow - keep a list of recent kernel exploits and check
uname -rearly.
References
- HackTheBox - Codify
- vm2 sandbox escape
- dirtyfrag LPE
- Lain Kusanagi list (OSCP prep)
