July 23, 2026
Sunset 1 Walkthrough: From Anonymous FTP to Root Access
Introduction & Machine Overview
By ANZIL Ca
10 min read
Introduction & Machine Overview
Sunset: 1 is a vulnerable Linux virtual machine created by developer whitecr0wz and hosted on VulnHub. It is designed as an entry-level "Boot2Root" challenge, where the ultimate objective is to gain initial access as an unprivileged user and subsequently escalate privileges to the root account to retrieve the final flag.
Intended Learning Objectives
This lab focuses on fundamental Linux penetration testing techniques and post-exploitation concepts, making it popular for candidates preparing for practical certifications like the OSCP (Offensive Security Certified Professional).
Key concepts demonstrated in this machine include:
- Network Service Enumeration: Identifying open network services (FTP and SSH) and recognizing potential misconfigurations such as unauthenticated anonymous access.
- Credential Harvesting: Extracting and analyzing exposed system backup files to recover stored password hashes.
- Offline Password Auditing: Performing offline hash cracking using wordlists (
rockyou.txt) and tools like John the Ripper without generating unnecessary network traffic or triggering account lockout policies. - Sudo Rights Auditing & GTFOBins: Inspecting
sudopermissions (sudo -l) and exploiting binaries configured with elevated execution rights (NOPASSWD) to escape the restricted environment into a root subshell.
1. Setting Up the Workspace
Before starting the assessment, I created a dedicated directory to keep scan outputs and evidence organized:
mkdir -p pentesting/sunset
cd pentesting/sunsetmkdir -p pentesting/sunset
cd pentesting/sunsetFigure 1: Setting up a dedicated workspace directory.
2. Finding the Target & Mapping the Attack Surface
Every lab starts with finding the target on the network. Since this VM gets its IP automatically via DHCP in VirtualBox, I needed to figure out what IP address it grabbed.
Hunting Down the Target IP
I kicked things off with an ARP scan across my local network segment:
sudo arp-scan -lsudo arp-scan -lFigure 2: Finding active hosts on the subnet using arp-scan.
arp-scan sends raw ARP requests across the local subnet (10.0.2.0/24). It operates at Layer 2 (Data Link layer), which means even if a host has a local firewall dropping ICMP pings, it still has to respond with its hardware (MAC) address.
How I Confirmed the Right IP
When running multiple VMs or host adapter interfaces, your subnet can get cluttered with virtual gateway addresses (10.0.2.1, 10.0.2.2, etc.). To make sure I was targeting the right host:
- I popped open VirtualBox, went into the Sunset VM settings, and checked Network →Advanced.
- The network interface showed a MAC address ending in
F0:F0:ED. - Looking back at my
arp-scanresults, only one host matched that MAC suffix:10.0.2.5.
That confirmed my target IP without any guesswork.
Port & Service Enumeration (Nmap)
With the IP locked in, I ran an aggressive Nmap scan to see what ports were open and what services were listening behind them:
sudo nmap -A 10.0.2.5sudo nmap -A 10.0.2.5Figure 3: Nmap scan results showing exposed FTP and SSH services.
Why I Used -A:
The -A flag is my go-to for initial box enumeration because it bundles several useful scans together in one pass:
- Service Versioning (
-sV): Grabs banners to tell us exactly what software versions are running. - Default Scripts (
-sC): Runs standard security checks for common misconfigurations or quick wins. - OS Detection (
-O): Tries to fingerprint the operating system kernel.
What the Scan Found
PORT STATE SERVICE VERSION
21/tcp open ftp pyftpdlib 1.5.5
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 root root 1062 Jul 29 2019 backup
22/tcp open ssh OpenSSH 7.9p1 Debian 10 (protocol 2.0)PORT STATE SERVICE VERSION
21/tcp open ftp pyftpdlib 1.5.5
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 root root 1062 Jul 29 2019 backup
22/tcp open ssh OpenSSH 7.9p1 Debian 10 (protocol 2.0)We have two ports standing out:
- Port 21 (FTP):
- Nmap's default scripts immediately flagged that Anonymous login is enabled. On top of that, the script output listed an interesting file sitting right in the FTP directory: a file named
backupowned byroot. - Port 22 (SSH):
- Standard SSH running on Debian 10 (Buster).
Step 3: FTP Enumeration & Credential Extraction
Since Port 21 was open and Nmap flagged Anonymous FTP access, this was naturally my first target. Anonymous FTP means the server is configured to let anyone log in without a registered account or a password.
Connecting to the FTP Server
To check what files were exposed, I connected directly to the FTP service using the standard Linux command-line client:
ftp 10.0.2.5ftp 10.0.2.5When prompted for credentials:
- Name:
anonymous - Password: (Left blank — just press Enter)
The server accepted the login right away with a 230 User logged in message.
Exploring the Directory & Downloading the File
Once inside the interactive FTP prompt, I listed all files — including hidden ones — to see what was sitting on the server:
ftp> ls -la
-rw-r--r-- 1 root root 1062 Jul 29 2019 backupftp> ls -la
-rw-r--r-- 1 root root 1062 Jul 29 2019 backupThere it was: the 1062-byte file named backup owned by root.
Since standard FTP interfaces don't let you directly view file contents (you can't just run cat or less inside an FTP prompt), I downloaded the file to my local machine using the get command, then exited the session:
ftp> get backup
200 PORT command successful.
150 Opening BINARY mode data connection for backup (1062 bytes).
226 Transfer complete.
ftp> exitftp> get backup
200 PORT command successful.
150 Opening BINARY mode data connection for backup (1062 bytes).
226 Transfer complete.
ftp> exitInspecting the Stolen File
Back on my local Kali machine, I used cat to inspect what was inside the downloaded backup file:
cat backupcat backupOutput:
CREDENTIALS:
office:$6$$9ZYTy.VI0M7cG9tVcPl.QZZi2XHOUZ9hLsiCr/avWTajSPHqws7.75I9ZjP4HwLN3Gvio5To4gjBdeDGzhq.X.
datacenter:$6$$3QW/J4OlV3naFDbhuksxRXLrkR6Iko4gh.Zx1RfZC2OINKMiJ/6Ffyl330FtBvCI7S4N1b8vLDylF2hG2N0NN/
sky:$6$$Ny8IwgIPYq5pHGZqyIXmoVRRmWydH7u2JbaTo.H2kNG7hFtR.pZb94.HjeTK1MLyBxw8PEuyzJszcwfH0qepG0
sunset:$6$$406THujdibTNu./R$NzquK0QRsbAUUSrHcpR2QrrlU3fA/SJo7sPDPBp3xcCR/lpbgMXS67Y27KtgLZAcJq9KZpEKEqBHFLzFSZ9bo/
space:$6$$4NccGQWPfiyfGKHgyhJBgiadOlP/FM4.Qwl1yIWP28ABx.YuOsiRaiKKU.4A1HKs9XLXtq8qFuC3W6SCE4Ltx/CREDENTIALS:
office:$6$$9ZYTy.VI0M7cG9tVcPl.QZZi2XHOUZ9hLsiCr/avWTajSPHqws7.75I9ZjP4HwLN3Gvio5To4gjBdeDGzhq.X.
datacenter:$6$$3QW/J4OlV3naFDbhuksxRXLrkR6Iko4gh.Zx1RfZC2OINKMiJ/6Ffyl330FtBvCI7S4N1b8vLDylF2hG2N0NN/
sky:$6$$Ny8IwgIPYq5pHGZqyIXmoVRRmWydH7u2JbaTo.H2kNG7hFtR.pZb94.HjeTK1MLyBxw8PEuyzJszcwfH0qepG0
sunset:$6$$406THujdibTNu./R$NzquK0QRsbAUUSrHcpR2QrrlU3fA/SJo7sPDPBp3xcCR/lpbgMXS67Y27KtgLZAcJq9KZpEKEqBHFLzFSZ9bo/
space:$6$$4NccGQWPfiyfGKHgyhJBgiadOlP/FM4.Qwl1yIWP28ABx.YuOsiRaiKKU.4A1HKs9XLXtq8qFuC3W6SCE4Ltx/Breaking Down What We Found
This was a massive lead. The backup file handed over five valid system usernames (office, datacenter, sky, sunset, and space) along with their encrypted password hashes.
If you look closely at the hash format, you can tell exactly how Linux encrypted them:
- The
$6$Prefix: In Linux systems (like/etc/shadow),$6$signifies that the password was hashed using SHA-512 crypt, a heavy cryptographic algorithm. - The Salt & Hash Body: The characters following
$6$contain the unique salt (used to prevent rainbow table attacks) and the scrambled password string.
Step 4: Offline Password Cracking
Now that we had five valid system accounts and their SHA-512 hashes from the backup file, we needed to crack those scrambled strings into plaintext passwords so we could log in via SSH.
Why Crack Offline?
Brute-forcing SSH across the network is slow, noisy, and risks triggering firewall rules or locking out accounts. Because the target leaked raw hashes in the backup file, we can perform offline password cracking locally on our Kali machine:
- Zero Network Traffic: The target server has no idea we are testing millions of passwords.
- Maximum Performance: Cracking runs locally as fast as your hardware can compute them.
Understanding John the Ripper (JtR)
To crack the hashes, I used John the Ripper (JtR), an industry-standard, open-source offline password auditing tool built into Kali Linux.
How John the Ripper Works Under the Hood
- One-Way Cryptographic Nature: Cryptographic hashes (like SHA-512 crypt
$6$) are designed as one-way mathematical functions. You cannot simply "reverse" or "decrypt" a hash back into plaintext. - The Guess-and-Check Loop: To recover a password, John takes a plain text string from a wordlist (such as
rockyou.txt), appends the target account's salt, runs it through the exact same SHA-512 algorithm, and compares the resulting hash against our target file. - Efficiency & Auto-Detection: John automatically detects hash signatures (like
$6$for Linux SHA-512 crypt) and leverages multi-threading across your CPU cores to calculate thousands of hashes per second.
Isolating Hashes into Individual Files with nano
Instead of throwing all five hashes into a single file together, I created a separate text file for every user (sunset.txt, sky.txt, office.txt, space.txt, and datacenter.txt).
Splitting hashes into individual files using a terminal text editor like nano is a clean habit:
- It lets you focus cracking attempts on one specific account at a time.
- It keeps your output organized and easy to track.
- It avoids confusing John the Ripper when dealing with multiple unique salts
To isolate the hash for user sunset, I opened nano:
nano sunset.txtnano sunset.txtInside nano, I pasted just the raw hash string for sunset:
$6$$406THujdibTNu./R$NzquK0QRsbAUUSrHcpR2QrrlU3fA/SJo7sPDPBp3xcCR/lpbgMXS67Y27KtgLZAcJq9KZpEKEqBHFLzFSZ9bo/$6$$406THujdibTNu./R$NzquK0QRsbAUUSrHcpR2QrrlU3fA/SJo7sPDPBp3xcCR/lpbgMXS67Y27KtgLZAcJq9KZpEKEqBHFLzFSZ9bo/I saved and closed the file (Ctrl + O, Enter, Ctrl + X), then repeated this process for the remaining four user hashes in their own respective files.
Running John the Ripper Across the Users
With each user's hash isolated in its own file, I ran John the Ripper against each file using the rockyou.txt wordlist:
john sunset.txt --wordlist=/usr/share/wordlists/rockyou.txtjohn sunset.txt --wordlist=/usr/share/wordlists/rockyou.txtOut of the 5 account hashes tested, John successfully cracked passwords for 3 users:
sunset:cheer14sky: (Cracked)space: (Cracked)
Result Focus: User sunset
Since any valid account gives us a foot in the door, I selected sunset to establish our initial SSH connection:
- Target Account:
sunset - Cracked Password:
cheer14
With verified credentials ready, we moved straight to logging into the target machine via SSH.
Step 5: Initial Access via SSH
With valid credentials in hand for the sunset user (sunset:cheer14), it was time to move from external recon to active internal access.
Since SSH (Secure Shell) was open on port 22, we could log straight into an interactive command-line shell on the target machine without needing reverse shells or web exploits.
Logging In Over SSH
From my local terminal, I initiated the SSH connection
ssh sunset@10.0.2.5ssh sunset@10.0.2.5Handling the SSH Host Key Prompt
If this is your first time connecting to a newly deployed target VM, SSH will prompt you with a fingerprint verification warning:
The authenticity of host '10.0.2.5 (10.0.2.5)' can't be established.
ED25519 key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no/[fingerprint])?The authenticity of host '10.0.2.5 (10.0.2.5)' can't be established.
ED25519 key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no/[fingerprint])?This is standard behavior — SSH is asking whether to trust the target machine's host key and add it to your local ~/.ssh/known_hosts file. Type yes and press Enter.
When prompted for the password, enter cheer14 (note that Linux won't echo asterisks or characters on screen while typing passwords):
sunset@10.0.2.5's password: cheer14sunset@10.0.2.5's password: cheer14Validating the Compromised Shell
Once authenticated, the terminal prompt changed to sunset@sunset:~$, confirming a successful login!
To orient myself and double-check my privilege level, I ran a few quick discovery commands:
whoami
# Output: sunset
id
# Output: uid=1000(sunset) gid=1000(sunset) groups=1000(sunset)...
pwd
# Output: /home/sunsetwhoami
# Output: sunset
id
# Output: uid=1000(sunset) gid=1000(sunset) groups=1000(sunset)...
pwd
# Output: /home/sunsetThis confirmed two important details:
- We are running as an unprivileged local user (
uid=1000). - We landed directly in
/home/sunset.
Retrieving the User Flag
In most CTF or pentesting assessments, user flags are placed inside the home directory of the initial account. Listing the contents of /home/sunset confirmed this:
ls -lals -laOutput:
drwxr-xr-x 2 sunset sunset 4096 Jul 29 2019 .
drwxr-xr-x 7 root root 4096 Jul 29 2019 ..
-rw-r--r-- 1 sunset sunset 33 Jul 29 2019 user.txtdrwxr-xr-x 2 sunset sunset 4096 Jul 29 2019 .
drwxr-xr-x 7 root root 4096 Jul 29 2019 ..
-rw-r--r-- 1 sunset sunset 33 Jul 29 2019 user.txtTo read the flag, I ran cat:
cat user.txtcat user.txtWith the user flag secured, the first major objective was complete. Now, the final goal was privilege escalation — finding a misconfiguration or vulnerability that would let us move from sunset up to root.
Step 6: Escalating Privileges to Root
Getting a footprint on the system as an unprivileged user (sunset) is a great start, but our ultimate objective in any Boot2Root lab is obtaining full administrative control (root).
With interactive access secured, the next logical phase was internal enumeration — checking local configurations for quick privilege escalation vectors.
Auditing Sudo Permissions (sudo -l)
One of the first commands I always run after landing an SSH session is sudo -l. This command lists all allowed commands that the current user can execute with sudo (elevated privileges) according to the system's /etc/sudoers file.
sudo -lsudo -lWhen prompted for sunset's password, I entered cheer14.
Output:
Matching Defaults entries for sunset on sunset:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User sunset may run the following commands on sunset:
(root) NOPASSWD: /usr/bin/edMatching Defaults entries for sunset on sunset:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User sunset may run the following commands on sunset:
(root) NOPASSWD: /usr/bin/edThis was a massive finding! The output tells us that sunset is allowed to run the /usr/bin/ed binary as root without having to supply a root password (NOPASSWD).
The Security Risk: GTFOBins & Shell Escapes
Why is letting a regular user run ed with sudo so dangerous?
ed is a classic line-oriented text editor in Unix systems. Like many command-line utilities (such as vim, less, man, or gdb), ed includes a built-in feature called a shell escape.
- Typing ! inside
edinstructs the program to pause the editor and execute a command directly in the host's default shell (like Bash). - Because
edwas invoked withsudo(asroot), any subprocess spawned from insideedautomatically inherits that samerootsecurity context!
This technique is widely documented on GTFOBins — a curated list of Unix binaries that can be abused to bypass local security restrictions in misconfigured systems.
Executing the Root Privilege Escalation
Exploiting this misconfiguration takes just a couple of quick commands.
1. Launch ed with Elevated Privileges
First, start ed using sudo:
sudo /usr/bin/edsudo /usr/bin/edThis drops you into ed's minimal, promptless interface (you will just see a blank line or cursor waiting for input).
2. Escape to a Root Shell
Type ! followed by /bin/bash and press Enter:
!/bin/bash!/bin/bashThe editor executes /bin/bash in the background, spawning a brand-new interactive subshell with root authority!
Verifying Full Root Compromise
The terminal prompt immediately updated, signaling that we were no longer a regular user. To verify:
whoami
# Output: root
id
# Output: uid=0(root) gid=0(root) groups=0(root)whoami
# Output: root
id
# Output: uid=0(root) gid=0(root) groups=0(root)uid=0(root) confirms complete system compromise!
Claiming the Final Root Flag
With full administrative rights, I navigated to the root user's home directory to retrieve the final flag:
cd /root
ls -la
cat root.txtcd /root
ls -la
cat root.txtAnd just like that, Sunset: 1 was fully rooted!
Remediation & Key Takeaways
Completing a machine isn't just about grabbing the flags — it's about understanding why these vulnerabilities existed in the first place and how system administrators can prevent them in real-world environments.
Here are the main security lessons from Sunset: 1 and how to properly remediate each issue:
1. Secure FTP Configurations & Sensitive Data Exposure
- The Problem: The target ran an FTP service with anonymous login enabled, allowing unauthenticated users to browse the directory and download a sensitive system backup file containing hashed passwords.
- Why it Matters: Exposing internal backups or user data publicly gives attackers an immediate starting point for credential harvesting without generating suspicious login attempts.
- Remediation:
- Disable anonymous FTP access in your FTP server configuration (e.g., setting
anonymous_enable=NOinvsftpd.conf). - Never store system backups, credential lists, or sensitive configuration files inside public web or file-sharing directories.
- Restrict file permissions using the principle of least privilege so that sensitive files are only readable by essential administrative accounts.
2. Enforce Strong Password Policies
- The Problem: Multiple user accounts (
sunset,sky,space) used weak, predictable passwords that were easily recovered using a basicrockyou.txtwordlist during offline cracking. - Why it Matters: Even when password hashes are protected by strong cryptographic algorithms like SHA-512 crypt (
$6$), weak passwords can still be cracked offline in seconds once a hash file is leaked. - Remediation:
- Enforce strong password complexity policies requiring a minimum length (e.g., 14+ characters) and a mix of uppercase, lowercase, numbers, and symbols.
- Implement multi-factor authentication (MFA) for remote access services like SSH to ensure that leaked passwords alone aren't enough to grant access.
- Periodically audit user password hashes using tools like John the Ripper or Hashcat to catch weak user passwords internally before attackers do.
3. Tighten Sudo Rules & Limit Binary Capabilities
- The Problem: The user
sunsetwas grantedsudopermissions to run/usr/bin/edasrootwithout password authentication (NOPASSWD). Becauseedallows shell escapes (!), this effectively handed over complete root access to any user on the account. - Why it Matters: Delegating
sudorights to binaries that can execute system commands or open subshells (such as text editors, pagers, or archive tools) breaks security boundaries and creates an easy path to privilege escalation. - Remediation:
- Audit
/etc/sudoersregularly and strictly adhere to the Principle of Least Privilege. - Avoid granting
NOPASSWDrules for binaries capable of command execution or shell escapes (always reference resources like GTFOBins when auditing sudo privileges). - If a user only requires specific administrative tasks, consider using restricted wrappers, dedicated scripts with strict input validation, or Linux capabilities rather than giving broad binary execution permissions.
What I Learned From This Machine
Tackling Sunset: 1 was a great hands-on reminder of how real-world security breaches rarely happen through a single massive flaw. Instead, they happen through a chain of small misconfigurations:
Exposed FTP Backup →Weak Hashes →SSH Initial Access →Permissive Sudo Rule →Root Access
By analyzing both the attack paths and the defensive fixes, I gained a much clearer picture of how low-level technical oversights connect — and how crucial defensive hardening is to stopping an attacker at step one.