news 2026/7/2 2:47:30

CVE-2026-22218 Chainlit 框架任意文件读取漏洞全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CVE-2026-22218 Chainlit 框架任意文件读取漏洞全解析
  • 第一步:向 /project/element 发送 PUT 请求,在请求体中注入一个包含任意文件路径(如 /etc/passwd)的 path 字段,触发服务器读取该文件并缓存,同时通过 WebSocket 获得一个"文件令牌"(chainlitKey)

  • 第二步:携带这个文件令牌访问 /project/file/{chainlitKey},服务器直接把刚才读取的文件内容返回给攻击者

创建一个 demo.py

import chainlit as cl ​ ​ @cl.step(type="tool") async def tool(): # Fake tool await cl.sleep(2) return "Response from the tool!" ​ ​ @cl.on_message # this function will be called every time a user inputs a message in the UI async def main(message: cl.Message): """ This function is called every time a user inputs a message in the UI. It sends back an intermediate response from the tool, followed by the final answer. ​ Args: message: The user's message. ​ Returns: None. """ ​ ​ # Call the tool tool_res = await tool() ​ await cl.Message(content=tool_res).send()

利用 python 虚拟环境 方便搭建环境

python -m venv venv venv\Scripts\Activate.ps1 python -m pip install chainlit==2.9.3 #安装存在漏洞的 chainlit 版本 chainlit run demo.py -w

运行构造好的 chainlit_file_read_exploit.py 指定 url 和需要读取的文件内容,就可以将文件打印出来

漏洞分析

第一步是通过调用PUT /project/element​ 接口注入恶意文件路径,当攻击者在请求参数中传入包含任意路径的path​ 字段时(如/etc/passwd​),服务器端的persist_file()​ 函数会读取该路径指定的文件内容并将其复制到临时目录中,同时将临时文件路径与一个随机生成的文件标识符(file_id)建立映射关系并注入到当前会话的文件映射表(session.files)中,随后服务器通过 WebSocket 消息将这个文件标识符(chainlitKey)推送给客户端,攻击者需要监听 WebSocket 连接来捕获这个关键的文件ID。

server.py#update_thread_element

update_thread_element​ 函数接收到请求后,首先调用Element.from_dict()​ 方法解析请求体中的元素字典,该方法根据type​ 字段判断元素类型并创建对应的对象实例,当type​ 为custom​ 时会创建CustomElement​ 对象,随后服务器调用该对象的update()方法。

element.py#from_dict

在创建过程中from_dict()​ 方法会提取请求中的所有字段包括用户可控的path​ 字段并传递给对象构造函数,此时恶意路径(如/etc/passwd​)被完整保存到CustomElement​ 对象的path属性中。

【----帮助网安学习,以下所有学习资料免费领!加vx:YJ-2021-1,备注 “博客园” 获取!】

① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

element.py#CustomElement#update

调用CustomElement​的update()​ 方法,该方法内部会调用父类Element​ 的send()方法。

element.py#Element#send

首先send()​ 方法调用await self._create(persist=persist)执行文件持久化处理

element.py#Element#create

_create()​ 方法检测到对象存在path​ 属性后会调用session.persist_file()函数

session.py#BaseSession#persist_file

session.persist_file()​ 函数,该函数使用aiofiles​ 异步读取攻击者指定路径的文件内容,将内容复制到会话专属的临时目录中(如/tmp/chainlit/{session_id}/{file_id}​),同时生成一个随机的文件标识符(UUID格式),并在会话的文件映射表(session.files)中建立该标识符与临时文件路径的映射关系。

element.py#Element#send

成文件持久化后send()​ 方法执行第二个关键操作,调用await context.emitter.send_element(self.to_dict())将元素信息发送到前端

element.py#Element#to_dict

to_dict()​ 方法负责将CustomElement​ 对象转换为字典格式,该字典包含对象的所有关键属性如id​、type​、name​、display​ 以及最重要的chainlitKey(即刚才获得的文件标识符)

emitter.py#send_element

转换后的字典通过send_element()​ 方法传递给emitter​ 的emit函数

该函数是在 WebSocket 连接建立时注入到会话对象中的闭包函数,它调用 Socket.IO 的全局发送方法将包含chainlitKey​ 的元素字典通过 WebSocket 推送给客户端,攻击者通过监听 WebSocket 消息流捕获事件名为element​ 的消息,从消息数据中提取chainlitKey字段的值即可获得文件标识符,至此完成第一步的路径注入、文件复制和标识符获取操作。

第二步是使用第一步获得的文件标识符访问GET /project/file/{file_id}​ 接口来读取文件内容,服务器根据请求中的session_id​ 参数定位到对应的会话对象,从该会话的文件映射表中查找文件ID对应的临时文件路径,由于权限检查存在if current_user:​ 的逻辑缺陷,未认证用户可以绕过权限验证,服务器直接使用FileResponse返回临时文件的内容,而该临时文件已经是目标敏感文件的完整副本,从而实现任意文件读取,整个攻击过程无需任何身份认证,攻击者仅需建立一个匿名 WebSocket 连接即可完成利用。

server.py#get_file

get_file()​ 函数通过WebsocketSession.get_by_id()​ 方法根据session_id​ 从全局会话字典中获取对应的会话对象,从该会话对象的files​ 映射表中查找file_id​ 对应的文件记录,获取其中存储的临时文件路径,最后使用FileResponse()直接返回该临时文件的内容给客户端,由于临时文件已经是目标敏感文件的完整副本,攻击者成功获得任意文件的内容。

漏洞修复

目前官方已发布修复版本,建议用户尽快更新至 Chainlit 的修复版本或更高版本:Chainlit ≥ 2.9.4

官方在 2.9.4 版本中通过引入_sanitize_custom_element()​ 输入清理函数修复了该漏洞,该函数采用白名单机制重构了update_thread_element()​ 和delete_thread_element()​ 两个接口的元素处理逻辑,在创建 CustomElement 对象时仅提取并验证 id、name、display、props 等合法字段,而将用户可控的 path 字段从输入参数中完全排除,使得攻击者即使在请求中注入包含路径遍历字符的恶意 path 值,该字段也会在对象构造阶段被自动过滤丢弃,无法传递到后续的文件操作流程中,从根本上阻断了通过/project/element​ 接口注入任意文件路径并通过/project/file/{chainlitKey}接口读取敏感文件的攻击链,有效防止了路径遍历漏洞的利用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 2:47:05

ASP.NET Core 之 Identity 入门(一)

在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OWIN的东西,所以很多初学者在学习来很费劲&#xff…

作者头像 李华
网站建设 2026/7/2 2:46:05

MANO手部模型完整指南:如何用Python实现逼真3D手部建模

MANO手部模型完整指南:如何用Python实现逼真3D手部建模 【免费下载链接】MANO A PyTorch Implementation of MANO hand model. 项目地址: https://gitcode.com/gh_mirrors/ma/MANO 在当今的计算机视觉和人机交互领域,精确的手部建模已经成为实现自…

作者头像 李华
网站建设 2026/7/2 2:45:04

如何提取 Word 文档中的表格并导出为 Excel(Python 教程)

VBA (Visual Basic for Applications):Office 自带的脚本语言,可以快速将 Word 中的表格导出。虽然无需安装第三方库,但其语法陈旧、调试困难,且高度依赖 Microsoft Office 环境,无法在没有安装 Office 的服务器或 Lin…

作者头像 李华
网站建设 2026/7/2 2:45:05

AI编曲工具实战:从入门到专业音乐制作

1. 项目概述:AI编曲如何颠覆传统音乐制作流程十年前我第一次进录音棚帮朋友做伴奏,看到报价单时差点从椅子上摔下来——简单的钢琴鼓点编曲居然要价8000元。如今AI技术让音乐制作的门槛降低了至少90%,一个完全不懂乐理的小白用对工具也能在半…

作者头像 李华
网站建设 2026/7/2 2:40:21

C++集成OpenSSL实现RSA公钥加密:从原理到工程实践

1. 项目概述:为什么要在C里用OpenSSL玩转公钥加密?如果你正在用C开发一个需要安全传输数据的应用,比如一个客户端-服务器架构的聊天工具,或者一个需要保护本地配置文件的桌面软件,那么“公钥加密,私钥解密”…

作者头像 李华
网站建设 2026/7/2 2:39:34

如何彻底解决 AI 编程的连贯性难题

在生成式 AI 席卷软件工程的今天,越来越多的开发者习惯了让 AI 当自己的“结对编程伙伴”(Pair Programmer)。从几行代码的自动补全,到整个架构模块的自动生成,AI 的生产力毋庸置疑。然而,几乎所有深度依赖…

作者头像 李华