Skip to content

[BUG] Temporary Document Upload Path Traversal Vulnerability #5466

@Ro1ME

Description

@Ro1ME

问题描述 / Problem Description

Langchain-Chatchat 的临时文档上传接口 /knowledge_base/upload_temp_docs 存在路径遍历漏洞。攻击者可以通过构造恶意文件名,将文件写入到服务器任意位置,突破预期的临时目录限制。

漏洞类型: 路径遍历 (Path Traversal / Directory Traversal)
CVSS评分: 9.1 (Critical)
影响范围: 任意文件写入,可能导致服务器完全沦陷

复现问题的步骤 / Steps to Reproduce

  1. 启动 Langchain-Chatchat 服务

    python startup.py -a
  2. 构造恶意 multipart/form-data 请求,文件名包含路径遍历序列:

    curl -X POST "http://127.0.0.1:7861/knowledge_base/upload_temp_docs" \
      -F "files=@test.json;filename=..\\..\\..\\malicious.json"
  3. 观察文件被写入到运行时根目录外

  4. 漏洞触发,文件成功逃逸临时目录

预期的结果 / Expected Result

  • 文件应该被写入到 {temp_dir}/{request_id}/ 目录下
  • 文件名应该经过路径规范化和边界检查
  • 包含 .. 的文件名应该被拒绝或清理

实际结果 / Actual Result

  • 文件被写入到 D:\Project\Dataset\Langchain-Chatchat\.runtime-full-root\file-chat-escape.json

  • 成功逃逸了预期的临时目录边界

  • 服务器返回 HTTP 200,虽然后续解析失败,但文件已经写入

  • 响应内容:

    {
      "code": 200,
      "msg": "success",
      "data": {
        "id": "19c24fe39aa94219bc7125cc913c4a33",
        "failed_files": [
          {
            "..\\..\\..\\file-chat-escape.json": "文件上传失败,报错信息为: jq package not found"
          }
        ]
      }
    }

漏洞根因 / Root Cause

受影响文件: libs/chatchat-server/chatchat/server/chat/file_chat.py:52
受影响函数: _parse_files_in_thread

该函数直接使用用户提供的文件名构造文件路径,未进行路径规范化或边界检查:

def _parse_files_in_thread(
    files: List[UploadFile],
    dir: str,
    zh_title_enhance: bool,
    chunk_size: int,
    chunk_overlap: int,
):
    for file in files:
        filename = file.filename  # 直接使用用户输入
        file_path = os.path.join(dir, filename)  # 未进行边界检查
        # ... 直接写入文件

安全影响 / Security Impact

严重性: CRITICAL

  1. 任意文件写入: 攻击者可以覆盖服务器上的任意文件
  2. 代码执行: 可以覆盖 Python 模块或配置文件实现远程代码执行
  3. 权限提升: 可以修改系统配置文件
  4. 拒绝服务: 可以覆盖关键系统文件导致服务崩溃

攻击场景示例:

  • 覆盖 startup.py 注入恶意代码
  • 覆盖 .env 配置文件窃取 API 密钥
  • 覆盖 Python 库文件实现持久化后门

修复建议 / Recommended Fix

import os
from pathlib import Path

def _parse_files_in_thread(
    files: List[UploadFile],
    dir: str,
    zh_title_enhance: bool,
    chunk_size: int,
    chunk_overlap: int,
):
    # 规范化基础目录
    base_dir = Path(dir).resolve()
    
    for file in files:
        # 清理文件名,移除路径分隔符
        filename = os.path.basename(file.filename)
        
        # 构造完整路径并规范化
        file_path = (base_dir / filename).resolve()
        
        # 边界检查:确保文件在预期目录内
        if not str(file_path).startswith(str(base_dir)):
            raise ValueError(f"Invalid filename: {file.filename}")
        
        # 继续处理...

环境信息 / Environment Information

  • Langchain-Chatchat 版本 / commit 号: Latest (commit from 2026-04-12)
  • 部署方式(pypi 安装 / 源码部署 / docker 部署): 源码部署 / dev deployment
  • 使用的模型推理框架(Xinference / Ollama / OpenAI API 等): 不适用(漏洞与模型无关)
  • 使用的 LLM 模型(GLM-4-9B / Qwen2-7B-Instruct 等): 不适用
  • 使用的 Embedding 模型(bge-large-zh-v1.5 / m3e-base 等): 不适用
  • 使用的向量库类型 (faiss / milvus / pg_vector 等): 不适用
  • 操作系统及版本 / Operating system and version: Windows 10 / Windows Server
  • Python 版本 / Python version: 3.8+
  • 推理使用的硬件(GPU / CPU / MPS / NPU 等) / Inference hardware: 不适用
  • 其他相关环境信息 / Other relevant environment information: 完整服务启动(python startup.py -a

附加信息 / Additional Information

验证证据:

  • 完整的 HTTP 请求/响应日志
  • 文件系统副作用证明(文件确实被写入到运行时根目录)
  • 自动化 PoC 脚本可供复现

相关漏洞: 该项目还存在另外两个类似的路径遍历漏洞:

  • /knowledge_base/upload_docs (知识库文档上传)
  • /v1/files (OpenAI 兼容 API)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions