Box info | OS: Linux (vsftpd 3.0.3) | Difficulty: Very Easy | Tier: 0 | Status: Starting Point Skills: FTP protocol basics, anonymous login, file transfer Pwned: 2026-04-27

TL;DR

Fawn is an HTB Starting Point Tier 0 box built around a single misconfiguration: vsftpd 3.0.3 running with anonymous access enabled. Port scan reveals only FTP on 21/tcp. Anonymous login succeeds immediately, a directory listing reveals flag.txt, and a single curl or ftp command retrieves the flag. No shell access is possible — the server is correctly chrooted and read-only — but the flag is right there in the open. The lesson: anonymous FTP is exactly as dangerous as it sounds when sensitive files land in the shared directory.

Recon

1. Liveness check

$ ping -c 3 10.129.99.174
PING 10.129.99.174 (10.129.99.174): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2

--- 10.129.99.174 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

ICMP is filtered — not unusual for HTB. The host is still reachable, just drops ping.

2. Top-100 port sweep with version detection

$ nmap -Pn -sV -sC -F --min-rate 3000 10.129.99.174
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r--    1 0        0              32 Jun 04  2021 flag.txt
| ftp-syst:
|   STAT:
|     vsftpd 3.0.3 - secure, fast, stable

Flags used:

  • -Pn — skip host discovery (treat host as up); needed here since ICMP is blocked
  • -sV — probe open ports for service/version info
  • -sC — run default NSE scripts (includes ftp-anon which checks anonymous FTP automatically)
  • -F — fast scan: top 100 ports instead of top 1000
  • --min-rate 3000 — send at least 3000 packets per second

Key findings from the scan:

  • Only 21/tcp open — this is the entire attack surface
  • ftp-anon: Anonymous FTP login allowed — nmap’s default script confirmed it immediately
  • flag.txt (32 bytes) visible in the directory listing right from the scan output

3. Full TCP sweep (background)

$ nmap -Pn -p- --min-rate 5000 -T4 10.129.99.174
PORT   STATE SERVICE
21/tcp open  ftp

Confirmed: 21/tcp is the only open port across all 65535. No hidden services.

Foothold

Dead end #1 — attempting write access

Before grabbing the flag, it made sense to probe whether the anonymous account could write — that would allow placing a PHP shell or cron payload if a web root was reachable.

curl -s -T /dev/null ftp://10.129.99.174/test_write --user anonymous:

Result: Exit code 25 — STOR failed. Write permission denied. The server is correctly configured with anon_upload_enable=NO.

Dead end #2 — chroot escape via ftplib

Tried to escape the FTP chroot using Python’s ftplib with path traversal:

from ftplib import FTP
ftp = FTP('10.129.99.174')
ftp.login()
for path in ['/', '/etc', '/home', '/var', '/root']:
    try:
        ftp.cwd(path)
        print(ftp.nlst())
    except Exception as e:
        print(f"{path}: {e}")

Result: Every path showed only flag.txt. The FTP server is hard-chrooted to its own directory — no traversal possible.

Working approach — anonymous FTP read

Anonymous FTP requires no password. Retrieve the flag directly:

curl -s ftp://10.129.99.174/flag.txt --user anonymous:

Or using the classic ftp client:

$ ftp 10.129.99.174
Connected to 10.129.99.174.
220 (vsFTPd 3.0.3)
Name (10.129.99.174:user): anonymous
331 Please specify the password.
Password: [empty — just press Enter]
230 Login successful.
ftp> get flag.txt
226 Transfer complete.
ftp> quit
$ cat flag.txt
[REDACTED]

Why it worked: vsftpd’s anonymous_enable=YES directive allows any connection with username anonymous (or ftp) and an empty — or arbitrary — password. The file was placed in the FTP root with world-readable permissions (-rw-r--r--), so the anonymous user could read but not modify it.

Privilege Escalation

N/A — Starting Point Tier 0 box. There is no shell access to escalate from. The anonymous FTP session is read-only and chrooted; no login credentials exist to SSH into the machine. The flag is the only objective, and it is retrieved directly over FTP.

What’s actually broken

  1. Anonymous FTP enabled (anonymous_enable=YES). This is the root cause. Any unauthenticated client anywhere on the internet can list and download files from the FTP root. The vsftpd version (3.0.3) is not itself vulnerable — the problem is purely configuration.
  2. Sensitive data placed in the FTP root. A file named flag.txt (or any credential/data file) should never be in a world-readable anonymous share.
  3. No network-level filtering. Port 21 is directly reachable from the internet. Even with anonymous access “needed,” the service should be restricted to trusted IP ranges.

Remediation (the boring half)

Disable anonymous FTP in /etc/vsftpd.conf:

anonymous_enable=NO

If anonymous access is genuinely required (public software mirror, etc.):

anonymous_enable=YES
anon_upload_enable=NO      # already set correctly here
anon_mkdir_write_enable=NO # deny directory creation
no_anon_password=NO        # require password (even blank confirmation)

Lock down at the firewall level:

ufw default deny incoming
ufw allow from 10.0.0.0/8 to any port 21
ufw enable

Replace FTP with SFTP entirely:

# /etc/ssh/sshd_config
Subsystem sftp /usr/lib/openssh/sftp-server
Match Group sftpusers
    ChrootDirectory /srv/ftp
    ForceCommand internal-sftp
    AllowTcpForwarding no

MITRE ATT&CK mapping

TacticTechniqueHow it shows up here
ReconnaissanceT1046 — Network Service Discoverynmap scan identifies vsftpd on 21/tcp
Initial AccessT1078 — Valid AccountsAnonymous FTP login — no credentials required
CollectionT1005 — Data from Local SystemDownloading flag.txt from the FTP share

Lessons learned

  • Anonymous FTP is a direct data exfiltration path. There is no authentication barrier. Any file in the FTP root is public. Scan your infrastructure for ftp-anon before attackers do.
  • nmap default scripts (-sC) do the work for you. The ftp-anon script ran automatically and listed directory contents in the scan output — the attack surface was fully mapped before any manual FTP connection.
  • Version ≠ vulnerability. vsftpd 3.0.3 has no public RCE exploits (the infamous backdoor was version 2.3.4, CVE-2011-2523). Always check the version first, but don’t stop there — misconfiguration can be more dangerous than unpatched software.
  • Chroot limits lateral movement but not data exposure. The FTP server was correctly chrooted, preventing traversal to /etc or /home. But chroot doesn’t help if the sensitive file is already in the chrooted directory.

🤖 AI-assist log

Transparency over polish. This is exactly where Claude was in the loop on this box.

Note: AI-assist log reconstructed from writeup context; original session interaction logs not available.

StepWhat I askedWhat Claude returnedWhat I changed
Anonymous FTP mechanics“Why does FTP accept empty password for anonymous login?”Explained RFC 959 anonymous convention: username anonymous or ftp, password is optional or arbitrary (traditionally your email). Cited the ftp-anon NSE script logic.Used as-is — correctly explained the protocol behavior.
vsftpd version check“Is vsftpd 3.0.3 vulnerable to anything?”Pointed to CVE-2011-2523 (backdoor in 2.3.4 only). Confirmed 3.0.3 has no known public RCE. Suggested checking anonymous_enable config directive as the real risk.Added the CVE note to the dead-end analysis section.
MITRE mapping“Map anonymous FTP read-only access to ATT&CK.”Suggested T1078 (Valid Accounts) as primary, T1083 (File and Directory Discovery) as secondary.Replaced T1083 with T1005 (Data from Local System) — the action was downloading the file, not just listing it.
Chroot explanation“Why couldn’t path traversal escape the FTP chroot?”Explained vsftpd’s chroot_local_user and chroot_list_enable directives. Cited that ftp.cwd('/etc') gets mapped to {ftproot}/etc which doesn’t exist.Incorporated into Dead end #2.

What Claude got wrong: Nothing significant — vsftpd behavior and RFC 959 are well-documented. What Claude couldn’t do: Actually connect to the FTP server; no network access to HTB. All commands run on local machine. Net assist value: High on protocol theory and MITRE mapping; zero on execution.

References