CVE-2026-39262分析|rag-web-uiRAG越权问题

admin 2026-09-13 05:17:27 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文分析rag-web-ui在0.7.5版本前存在的越权漏洞,任意登录用户可通过枚举文件ID拦截他人临时文档并导入自身知识库,导致信息泄露。根本原因是后端在处理文档时未校验文件所有者,且文件ID可顺序枚举。建议立即升级版本并增加权限校验机制。 综合评分: 85 文章分类: 漏洞分析,WEB安全,安全开发


CVE-2026-39262 分析 | rag-web-ui RAG 越权问题

原创

AugustTheodor AugustTheodor

重生之成为赛博女保安

2026年9月11日 11:11 吉林

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

前言

本来我是懒得写的。但是最近AI安全系列文章的收视率太低了^ ^。

漏洞范围

earlier than 0.7.5

漏洞编号

CVE-2026-39262

漏洞详情

rag-web-ui是一个RAG知识库管理系统(下称该系统)。在上传文档时,任意登陆用户可以拦截其他用户的临时文档并导入到自己的知识库,从而造成信息泄露。

要了解这个漏洞的成因,我们得先从其文件上传逻辑看起。在该系统中,文档上传分为三个步骤:上传-预览-处理,如下图所示。

该系统使用minio作为文档存储组件。在用户上传文档时,该系统会先将文档存储到minio,然后返回一个文件id(文件名)作为后续处理操作的索引参数。

这个设计本身没有什么问题,问题在于:

①在后续两个步骤中,前端接收的参数为文件名,而这个文件名是可顺序枚举的。

②在处理步骤拉取文件到知识库时,后端没有对文件所有者进行校验。

了解原理之后我们进一步来看代码。

/{kb_id}/documents/upload 用于真正上传文档,可以看到,它会直接将文件放入存储桶并返回文件名。

@router.post("/{kb_id}/documents/upload")async def upload_kb_documents(    kb_id: int,    files: List[UploadFile],    db: Session = Depends(get_db),    current_user: User = Depends(get_current_user)):
   # 上略......        upload = DocumentUpload(            knowledge_base_id=kb_id,            file_name=file.filename,            file_hash=file_hash,            file_size=len(file_content),            content_type=file.content_type,            temp_path=temp_path        )        db.add(upload)        db.commit()        db.refresh(upload)
           results.append({            "upload_id": upload.id, # 这个ID初始化中没有明文传入,那么它的值就取决于ORM的赋值逻辑            "file_name": file.filename,            "temp_path": temp_path,            "status": "pending",            "skip_processing": False        })
    return results

如上文,我们找到DocumentUpload的声明位置,可以看到这个id是顺序自增的:

/{kb_id}/documents/process 用于第三步处理文档,也是在这一步攻击者可以通过枚举file_id来拉取其它用户上传的文件。

@router.post("/{kb_id}/documents/process")async def process_kb_documents(    kb_id: int,    upload_results: List[dict],    background_tasks: BackgroundTasks,    db: Session = Depends(get_db),    current_user: User = Depends(get_current_user)):    # 上略......
    uploads = db.query(DocumentUpload).filter(DocumentUpload.id.in_(upload_ids)).all()     # 这里只通过文档id(upload_id)查询文档,所以当文档可枚举时,可以拉取到任意用户的文档
    # 下略......
    return {"tasks": task_info}

当然写到这里有读者可能会有疑问了:既然第三步是通过file_id取的,那第二步呢?第二步里存在类似的越权吗?这个问题我也求证过了,很遗憾答案是没有:

这个项目的经手人比较多+Vibe Coding的工作方式,不同端点之间出现这样的水平差异很正常。

POC

POST /{kb_id}/documents/process&nbsp;Content-Type: application/json{[&nbsp; {&nbsp; &nbsp;&nbsp;"upload_id":&nbsp;"<id>",&nbsp; &nbsp;&nbsp;"skip_processing":&nbsp;true&nbsp; }]}

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:重生之成为赛博女保安 AugustTheodor AugustTheodor《CVE-2026-39262 分析 | rag-web-ui RAG 越权问题》

评论:0   参与:  0