← Back to list

WingData machine HTB

OS: Linux || Difficulty: Easy

Veen0o21 · 2026-02-22 15:08 · 3 claps · 3.6 min read
#htb #hackthebox #htb-writeup #hackthebox-writeup #hackthebox-walkthrough
Open on Medium ↗
Wiki topics: 🔓 · Open Source

WingData machine HTB

OS: Linux || Difficulty: Easy

.بسم الله والصلاة والسلام على أشرف خلق الله سيدنا محمد ﷺ وعلى آله وصحبه أجمعين

Shoutout to D3xter he spent days fighting that hash like it was personal I stepped in, cracked it in minutes, and kept it moving. Hope you took notes this time Dexyy.

Let’s dive in

started the box the way I start every machine: confirming connectivity and scanning everything.

The scan immediately revealed web and FTP services. While browsing the website, I noticed a redirect to wingdata.htb, so I added it to /etc/hosts.

Clicking on Client Portal changed the URL to ftp.wingdata.htb, which clearly indicated a subdomain handling FTP-related functionality. After adding it to /etc/hosts, the page loaded correctly.

At the bottom of the portal page, the exact version of Wing FTP Server was disclosed. That version number was the turning point.

Instead of randomly fuzzing, I searched specifically for vulnerabilities related to that exact version. A public exploit was available, and after reviewing the code carefully to understand what it actually did, it became clear that it allowed remote command execution.

I set up a listener:

nc -lvnp 4444

Then executed the exploit with a reverse shell payload. The connection came in successfully. The shell was basic, so I upgraded it:

python3 -c 'import pty; pty.spawn("/bin/bash")'

Now I had stable access.

From there, I started enumerating the system. Inside the filesystem, I found an XML configuration file related to the FTP server. That file contained credentials information specifically a SHA-256 hash for the user wacky.

The hash format matched Wing FTP’s implementation:

SHA256(password + "WingFTP")

So I saved the hash and used hashcat:

hashcat -m 1410 hash.txt rockyou.txt

The password cracked successfully.

With valid credentials, I logged in via SSH:

ssh wacky@wingdata.htb

User flag secured.

Now

Running:

sudo -l

revealed something powerful:

(root) NOPASSWD: /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py *

That script restores backup tar files. Looking into the source code, I saw it used:

tarfile.extractall(filter="data")

At first glance, this looks secure. The filter="data" parameter was introduced to prevent path traversal and unsafe extractions.

My first attempt was simple path traversal inside a tar archive:

../../../../root/.ssh/authorized_keys

Blocked.

Second attempt: symlink-based escape.

Also blocked.

The tarfile module was clearly hardened.

So I dug deeper.

Recent research pointed to CVE-2025–4138, which abuses Linux’s PATH_MAX limit (typically 4096 bytes). The issue is not a missing filter it’s a logical bypass involving how os.path.realpath() behaves when resolving very long paths.

Here’s the idea:

  • The filter validates extraction paths using realpath().
  • If the resolved path exceeds PATH_MAX, resolution stops behaving as expected.
  • The filter believes the path is safe.
  • During actual extraction, the Linux kernel fully resolves the symlink chain.
  • The file lands outside the intended directory.

Instead of attacking the filter directly, I abused filesystem limits.

I built a deeply nested symlink chain with extremely long directory names to inflate the resolved path beyond 4096 bytes. Inside that structure, I placed a file targeting:

/root/.ssh/authorized_keys

Before generating the archive, I created an SSH key that I intended to inject into root’s authorized keys:

ssh-keygen -f mykey -N ""

Using a custom Python script, I generated the final malicious archive containing the deep symlink structure.

However, I ran into a small but important mistake.

Initially, I named the archive:

backup_pwn.tar

The script rejected it immediately.

After reviewing the source code more carefully, I noticed a strict filename validation:

^backup_\d+\.tar$

The archive name must strictly follow this format:

backup_<numbers_only>.tar

Since pwn is not numeric, the script exited before even processing the archive.

This wasn’t a vulnerability failure it was my oversight.

I fixed it by renaming the file:

mv backup_pwn.tar backup_1337.tar

Then placed it inside the expected backups directory:

cp backup_1337.tar /opt/backup_clients/backups/

Finally, I triggered the restore script with sudo:

sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py -b backup_1337.tar -r restore_final

No errors.

No warnings.

At that point, it was just a matter of connecting:

ssh -i mykey root@localhost

Root access achieved.

See you in the next writeup, Insha’Allah.


메타데이터
post_id
89d5d46592ff
slug
wingdata-machine-htb-89d5d46592ff
url
https://medium.com/@Veen0o21/wingdata-machine-htb-89d5d46592ff
canonical_url
https://medium.com/@Veen0o21/wingdata-machine-htb-89d5d46592ff
author_url
https://medium.com/@Veen0o21
status
ok
fetched_at
2026-07-13 06:23:13