← back to writeups
Vulnhub

Vulnhub: Matrix 1

Matrix 1 is the original of the series and a clean lesson in clue-following plus restricted-shell escape. A base64 blob in page source points at a file encoded in Brainfuck, which leaks most of an SSH password; crunch and hydra finish the rest. The shell that credential opens is a restricted rbash, escaped through vi, and root is a single permissive sudo rule away.

Attack chain at a glance

  • Recon — SSH (22), HTTP (80), and an extra HTTP service on 31337; the pages hint “follow the white rabbit / Cypher.”
  • Clue chain — a base64 comment decodes to a reference to Cypher.matrix; that file is Brainfuck, which decodes to a username (guest) and a partial password (K1ll0r??).
  • Credential — crunch generates the 8-char candidates, hydra brute-forces SSH (weak/guessable password) to k1ll0r7n.
  • Foothold — SSH drops into a restricted rbash; escape it through vi's :!/bin/bash.
  • Root — reset PATH, then sudo -l allows a direct root shell.
Techniques in play: multi-layer decoding (base64 → Brainfuck), targeted wordlist generation with crunch + online/offline brute force with hydra, the classic vi restricted-shell breakout (a GTFOBins staple), and a permissive sudo rule.

Matrix 1 is the original of the series. The path: a base64-then-brainfuck clue chain that leaks a partial SSH password, crunch+hydra to finish it, a restricted-shell escape through vi, and a passwordless sudo for root.

Reconnaissance

Matrix 1 VM booted to a login prompt
The Matrix 1 VM at its login page.

netdiscover on the Kali host finds the target.

netdiscover showing the target at 192.168.145.133
Target identified as 192.168.145.133.

nmap shows SSH (22) and HTTP (80), plus an unusual HTTP port 31337. Port 80 greets us with the hint “follow the white rabbit.”

nmap results showing ports 22, 80 and 31337
SSH, HTTP, and HTTP on the non-standard 31337.

A nikto scan of port 80 finds nothing obviously exploitable.

nikto scan against port 80
nikto on port 80 — nothing actionable.

The clue chain

Moving to port 31337, the page's only heading is “Cypher.” A dirb scan (and another nikto) looks for anything cipher-related.

Port 31337 page showing only a Cypher heading
Port 31337 — just a “Cypher” heading.
dirb scan against port 31337
Directory brute-forcing the service…
nikto scan against port 31337
…and a nikto pass alongside it.

dirb finds an assets directory.

dirb finding an assets directory
An assets directory appears.

Inside is a file named port_31337.png.

assets directory listing with port_31337.png
The file port_31337.png.
Opening port_31337.png
Fetching the image.

It is a white rabbit — confirming we are on track — and its filename (the port) nudges us back to the page itself.

White rabbit image named after port 31337
The white rabbit: right path, keep looking.

Revisiting port 31337 and viewing the source reveals a commented-out ciphertext:

<!--p class="service__text">ZWNobyAiVGhlbiB5b3UnbGwgc2VlLCB0aGF0IGl0IGlzIG5vdCB0aGUgc3Bvb24gdGhhdCBiZW5kcywgaXQgaXMgb25seSB5b3Vyc2VsZi4gIiA+IEN5cGhlci5tYXRyaXg=</p-->
Hidden base64 ciphertext in the page source
The base64 blob hidden in an HTML comment.

Decoding the base64 in CyberChef yields a message ending in Cypher.matrix — which looks like a filename, so the URL is modified to request it.

Decoding the base64 to a Cypher.matrix reference
Decoded: a reference to Cypher.matrix.

The server immediately offers a file named Cypher.matrix for download. Its contents are a string of odd characters.

Downloaded Cypher.matrix file of strange characters
Cypher.matrix — an unfamiliar character soup.

The characters are Brainfuck.

Identifying the content as Brainfuck
Recognising the Brainfuck language.

An online Brainfuck interpreter reveals the message: the login username is guest, and the password is K1ll0r followed by two unknown characters.

Decoded Brainfuck message leaking a partial password
Username guest; password K1ll0r?? — last two characters unknown.

Finishing the password & SSH

crunch generates every 8-character candidate with the known K1ll0r prefix.

crunch generating an 8-character wordlist
Building the candidate wordlist with crunch.

hydra brute-forces SSH against that list.

hydra brute-forcing SSH with the generated list
Spraying the list at SSH with hydra.

It recovers the password: k1ll0r7n.

hydra returning the password k1ll0r7n
The full password: k1ll0r7n.

Restricted-shell escape & root

SSH drops us into a restricted bash. export shows the environment and the current path.

Restricted bash shell after SSH login
A locked-down rbash on login.

The path /home/guest/prog is readable, so its contents are inspected.

Inspecting /home/guest/prog
Looking at what lives in /home/guest/prog.

It is vi — a classic restricted-shell escape.

Discovering vi is runnable
vi is available — a known escape route.

From within vi, :!/bin/bash spawns a full shell.

Escaping the restricted shell via vi :!/bin/bash
:!/bin/bash breaks out to a real shell.

After resetting PATH so standard commands work, sudo -l shows root is available directly.

Resetting PATH in the new shell
Restoring a usable PATH.
sudo giving root and flag.txt in /root
sudo → root; flag.txt waits in /root.

Opening it gives the flag, and the box is done.

The root flag contents
The root flag — box complete.
Matrix 1 is pure clue-following: base64 → Brainfuck → a half-known password finished with crunch/hydra, then a textbook vi breakout and an open sudo rule. Enumeration does all the heavy lifting.

Defender's notes

  • Don't hide credentials in client-side encodings — encoding is not encryption; anyone can decode a comment or a served file.
  • Enforce strong, non-patterned passwords so a partial leak plus crunch/hydra can't finish the job (weak password policy).
  • A restricted shell (rbash) is not a security boundary when interpreters like vi/vim, less, or awk are reachable — restrict PATH and the available binaries, or don't rely on it.
  • Review sudo rules for least privilege.