
生成 67 个恶意 PDF 测试文件,用于测试 PDF 查看器、转换器和 Web 应用程序中的回呼、SSRF、XSS、XXE、NTLM 凭据窃取和数据泄露。可与 Burp Collaborator 或 Interact.sh 配合使用
用于渗透测试、漏洞赏金狩猎和/或红队活动等。创建此工具是因为我需要一个能生成大量包含各种链接的 PDF 文件的工具。仅用于教育和专业目的。
pip install -r requirements.txt python3 malicious-pdf.py burp-collaborator-url
输出将写入 `output/` 目录,文件名为:test1.pdf, test2.pdf, test3.pdf 等。
### 选项```
--output-dir DIR Directory to save generated PDF files (default: output/)
--no-credit Do not embed credit/attribution metadata in generated PDFs
--obfuscate LEVEL Obfuscation level (0-3):
0 = None (default)
1 = PDF name hex encoding + string octal/hex encoding
2 = Level 1 + JS bracket notation + javascript: URI case/whitespace obfuscation
3 = Level 2 + FlateDecode stream compression
带混淆的示例:``` python3 malicious-pdf.py https://your-interact-sh-url --obfuscate 2
最大混淆(级别4将JS负载包装在base64解码器存根中,因此原始API调用永远不会以字面子字符串形式出现):```
python3 malicious-pdf.py https://your-interact-sh-url --obfuscate 4
/V、base64 解码器)能击败简单的 /JS 正则扫描器Collab.isDocReadOnly(文件系统探测)、app.plugIns(枚举已安装插件)、app.viewerVersion(版本指纹识别)-O 标志的 PDFiD)会完全遗漏对象。参考:PDF 规范 ISO 32000 §7.5.7app.doc.getAnnots()[n].subject 检索并 eval。参考:Julia Wolf - 使用 getAnnots() 进行 PDF 混淆/Info 尾部字段(/Title、/Author)中。运行时通过 JS 中的 info.Title 检索。参考:corkami PDF 技巧/V 值中。通过 JS 中的 getField("name").value 检索。参考:corkami PDF 技巧/Names 条目中。参考:| 测试文件 | 函数 | CVE/参考 | 攻击向量 | 方法 | 影响 |
|---|
| test1.pdf | create_malpdf() | CVE-2018-4993 | 外部文件访问 | 带有 UNC 路径的 /GoToE 动作 | 通过文件系统的网络回调 |
| test1_1.pdf | create_malpdf() | CVE-2018-4993 | 外部文件访问 | 带有 HTTPS URL 的 /GoToE 动作 | 通过 HTTPS 的网络回调 |
| test2.pdf | create_malpdf2() | XFA 表单提交 | 表单数据泄露 | 带有提交事件的 XDP 表单 | 自动表单提交 |
| test3.pdf | create_malpdf3() | JavaScript 注入 | 代码执行 | 带有 app.openDoc() 的 /OpenAction | 外部文档加载 |
| test4.pdf | create_malpdf4() | CVE-2019-7089 | XSLT 注入 | 带有外部 XSLT 样式表的 XFA | UNC 路径回调 |
| test5.pdf | create_malpdf5() | PDF101 研究 | URI 动作 | /URI 动作类型 | DNS 预取/HTTP 请求 |
| test6.pdf | create_malpdf6() | PDF101 研究 | 启动动作 | 带有外部 URL 的 /Launch | 外部资源执行 |
| test7.pdf | create_malpdf7() | PDF101 研究 | 远程 PDF | /GoToR 动作 | 远程 PDF 加载 |
| test8.pdf | create_malpdf8() | PDF101 研究 | 表单提交 | 带有 HTML 标志的 /SubmitForm | 表单数据提交 |
| test9.pdf | create_malpdf9() | PDF101 研究 | 数据导入 | /ImportData 动作 | 外部数据导入 |
| test10.pdf | create_malpdf10() | CVE-2017-10951 | JavaScript 执行 | Foxit this.getURL() 回调 | 通过 Foxit Reader 的网络回调 |
| test11.pdf | create_malpdf11() | EICAR 测试 | AV 检测 | 嵌入的 EICAR 字符串 | 反病毒测试 |
| test12.pdf | create_malpdf12() | CVE-2014-8453 | FormCalc 数据泄露 | XFA FormCalc Post() 函数 | 带有 cookie 的同源数据泄露 |
| test13.pdf | create_malpdf13() | 请求注入 | CRLF 头部注入 | XFA 提交 textEncoding CRLF | HTTP 头部操纵 |
| test14.svg | create_malpdf14() | ImageMagick Shell 注入 | 通过 SVG/MSL 的 Shell 注入 | SVG-MSL 多语言文件 authenticate 属性 | 通过 ImageMagick 的远程代码执行 |
| test15.pdf | create_malpdf15() | PDF 规范 | FormCalc 头部注入 | 带有自定义头部的 XFA FormCalc Post() | 任意 HTTP 头部注入 |
| test16.pdf | create_malpdf16() | PDF 规范 | 通过 GotoE 的 JavaScript | 带有 javascript: URI 的 /GoToE | 当 PDF 通过 <embed>/<object> 嵌入时的浏览器 XSS |
| test17.pdf | create_malpdf17() | CVE-2014-8452 | XXE 注入 | XMLData.parse() 外部实体 | XML 外部实体解析 |
| test18.pdf | create_malpdf18() | PortSwigger 研究 | 注释 URI 注入 | 未转义括号通过重复的 /A 键注入 JS 动作 | 通过 PDF-Lib/jsPDF 输出的 XSS |
| test19.pdf | create_malpdf19() | PortSwigger 研究 | PV 自动执行 | /AA /PV 屏幕注释在页面可见时触发 JS | 自动代码执行(Acrobat) |
| test20.pdf | create_malpdf20() | PortSwigger 研究 | PC 关闭触发 | /AA /PC 注释在页面关闭时触发 JS | 关闭时代码执行(Acrobat) |
| test21.pdf | create_malpdf21() | PortSwigger 研究 | SubmitForm SubmitPDF | 带有 Flags 256 的 /SubmitForm 发送整个 PDF | 完整 PDF 内容泄露 |
| test22.pdf | create_malpdf22() | PortSwigger 研究 | JS submitForm() | this.submitForm() 带 cSubmitAs: "PDF" | PDF 内容提交(Acrobat) |
| test23.pdf | create_malpdf23() | PortSwigger 研究 | 小部件按钮注入 | 覆盖页面的不可见 /Btn 小部件,点击时触发 JS | 代码执行(Chrome/PDFium) |
| test24.pdf | create_malpdf24() | PortSwigger 研究 | 文本字段 SSRF | 带有 submitForm() POST 的 /Tx 小部件字段 | 通过表单数据的盲 SSRF |
| test25.pdf | create_malpdf25() | PortSwigger 研究 | 内容提取 | getPageNthWord() 读取所有文本并泄露 | 渲染文本泄露 |
| test26.pdf | create_malpdf26() | PortSwigger 研究 | 悬停触发 | 鼠标进入时触发 /AA /E 注释 JS | 悬停时代码执行(PDFium) |
| — | — | 已移除 | 重复 test3(Acrobat OpenAction JS)+ test23(Chrome Widget Btn) | — | |
| test28.pdf | create_malpdf28() | PortSwigger 研究 | URL 劫持 | 未转义括号注入新的 /URI 动作 | 通过 PDF-Lib/jsPDF 的点击重定向 |
| test29.pdf | create_malpdf29() | CVE-2024-4367 | FontMatrix 注入 | Type1 字体 FontMatrix 字符串跳出 c.transform() | PDF.js 中的任意 JS 执行(Firefox < 126) |
| test30.pdf | create_malpdf30() | PDF101 研究 | 外部 XObject 流 | 图像 XObject 通过 /FS /URL 从远程 URL 获取数据 | 通过页面渲染的静默回调(无动作/JS) |
| test31.pdf | create_malpdf31() | PDF101 研究 | 线程动作 | 带有远程 FileSpec 的 /S /Thread | 通过线程引用的网络回调 |
| test32.pdf | create_malpdf32() | PDF101 研究 | 带打印的启动 | 带有 /Win << /O /print >> 的 /Launch 强制远程获取 | 通过打印操作的网络回调 |
| test33_1.pdf | create_malpdf33_1() | PDF101 研究 | JS: this.submitForm() | Acrobat JS 表单提交回调 | Acrobat Reader |
| test33_2.pdf | create_malpdf33_2() | PDF101 研究 | JS: this.getURL() | Acrobat JS URL 获取 | Acrobat Reader |
| test33_3.pdf | create_malpdf33_3() | PDF101 研究 | JS: app.launchURL() | Acrobat JS 启动 URL | Acrobat Reader |
| test33_4.pdf | create_malpdf33_4() | PDF101 研究 | JS: app.media.getURLData() | Acrobat JS 媒体获取 | Acrobat Reader |
| test33_5.pdf | create_malpdf33_5() | PDF101 研究 | JS: SOAP.connect() | Acrobat JS SOAP 连接 | Acrobat Reader |
| test33_6.pdf | create_malpdf33_6() | PDF101 研究 | JS: SOAP.request() | Acrobat JS SOAP 请求 | Acrobat Reader |
| test33_7.pdf | create_malpdf33_7() | PDF101 研究 | JS: this.importDataObject() | Acrobat JS 数据导入 | Acrobat Reader |
| test33_8.pdf | create_malpdf33_8() | PDF101 研究 | JS: app.openDoc() | Acrobat JS 打开文档 | Acrobat Reader |
| test33_9.pdf | create_malpdf33_9() | PDF101 研究 | JS: fetch() | Web API 回调(PDF.js/浏览器) | Firefox/PDF.js |
| test33_10.pdf | create_malpdf33_10() | PDF101 研究 | JS: XMLHttpRequest | Web API 回调(PDF.js/浏览器) | Firefox/PDF.js |
| test33_11.pdf | create_malpdf33_11() | PDF101 研究 | JS: new Image() | Web API 图像回调(PDF.js/浏览器) | Firefox/PDF.js |
| test33_12.pdf | create_malpdf33_12() | PDF101 研究 | JS: WebSocket | Web API WebSocket 回调(PDF.js/浏览器) | Firefox/PDF.js |
| test33_13.pdf | create_malpdf33_13() | Adobe 0day 博客(2026 年 4 月) | JS: RSS.addFeed() | Acrobat JS RSS 订阅源回调 | Acrobat Reader |
| test33_14.pdf | create_malpdf33_14() | Adobe 0day 博客(2026 年 4 月) | JS: util.readFileIntoStream() + SOAP.request() | 本地文件读取 + 泄露链(try/catch 错误路径也会回调) | Acrobat Reader |
| test33_15.pdf | create_malpdf33_15() | Adobe 0day 博客(2026 年 4 月) | 表单字段分阶段 JS 加载器 | /Tx 小部件 /V 中的 Base64 载荷,通过 getField() + util.stringFromStream 解码 | Acrobat Reader |
| test34_1.pdf | create_malpdf34_1() | PDF101 研究 | UNC: XObject 流 | 带有 UNC 路径的图像 XObject | 通过页面渲染窃取 NTLM |
| test34_2.pdf | create_malpdf34_2() | PDF101 研究 | UNC: GoToR | 带有 UNC FileSpec 的 /GoToR 动作 | 通过远程 PDF 窃取 NTLM |
| test34_3.pdf | create_malpdf34_3() | PDF101 研究 | UNC: 线程 | 带有 UNC FileSpec 的 /Thread 动作 | 通过线程引用窃取 NTLM |
| test34_4.pdf | create_malpdf34_4() | PDF101 研究 | UNC: URI | 带有 UNC 路径的 /URI 动作 | 通过 URI 动作窃取 NTLM |
| test34_5.pdf | create_malpdf34_5() | PDF101 研究 | UNC: JS submitForm | 带有 UNC 路径的 this.submitForm() | 通过 JS 表单提交窃取 NTLM |
| test34_6.pdf | create_malpdf34_6() | PDF101 研究 | UNC: JS getURL | 带有 UNC 路径的 this.getURL() | 通过 JS URL 获取窃取 NTLM |
| test34_7.pdf | create_malpdf34_7() | PDF101 研究 | UNC: JS launchURL | 带有 UNC 路径的 app.launchURL() | 通过 JS 启动窃取 NTLM |
| test34_8.pdf | create_malpdf34_8() | PDF101 研究 | UNC: JS SOAP | 带有 UNC 路径的 SOAP.connect() | 通过 JS SOAP 窃取 NTLM |
| test34_9.pdf | create_malpdf34_9() | PDF101 研究 | UNC: JS openDoc | 带有 UNC 路径的 app.openDoc() | 通过 JS 打开文档窃取 NTLM |
| test35.pdf | create_malpdf35() | PDF101 研究 | 名称字典 | /Names /JavaScript 目录级别自动执行触发器 | 替代 JS 执行触发器 |
| test36.pdf | create_malpdf36() | CVE-2016-2175 / CVE-2017-9096 | XMP 元数据中的 XXE | /Metadata XMP 流中的 XXE <!ENTITY> | 服务器端回调(PDFBox, iText) |
| test37.pdf | create_malpdf37() | CVE-2016-2175 / CVE-2017-9096 | XFA 表单数据中的 XXE | /AcroForm /XFA 流中的 XXE <!ENTITY> | 服务器端回调(PDFBox, iText) |
| test38.pdf | create_malpdf38() | CVE-2020-29075 | 静默 DNS 追踪 | 带有 /WC、/WS、/DS 触发器的目录 /AA | 无提示的 DNS 回调(Acrobat) |
| test39.pdf | create_malpdf39() | CVE-2022-28244 | CSP 绕过 | 带有嵌入 HTML/JS 的 RichMedia 注释 | 跨域请求(Acrobat) |
| test40.pdf | create_malpdf40() | CVE-2018-5158 | PostScript 计算器注入 | 图像 XObject 中的 /FunctionType 4 JS 注入 | PDF.js worker 中的 JS 执行(Firefox) |
| test41.pdf | create_malpdf41() | CVE-2018-20065 | 无用户手势的 URI | 带有 /S /URI 自动导航的 /OpenAction | 静默导航(PDFium/Chrome) |
| test42.pdf | create_malpdf42() | CVE-2025-66516 | XFA 中的 XXE OOB 参数实体 | /AcroForm /XFA 中的 %xxe; 参数实体强制 DTD 获取 | 服务器端盲 XXE(Tika, Confluence, Jira) |
| test43.pdf | create_malpdf43() | CVE-2025-70401 | 注释 /T 字段 XSS | 文本注释 /T(作者)字段中的 `` 标签 | XSS 回调(Apryse WebViewer, web viewers) |
| test44.pdf | create_malpdf44() | CVE-2024-12426 | LibreOffice URL 展开 | 带有 vnd.sun.star.expand: 的 /URI 展开 ${HOME} | 环境变量泄露(LibreOffice < 24.8.4) |
| test45.pdf | create_malpdf45() | CVE-2025-59803 | 签名时的 OCG JS 触发 | /AA /WP+/DP 在签名工作流中通过 OCG 触发 JS | 签名过程中的回调(Foxit < 2025.2.1) |
| test46.pdf | create_malpdf46() | CVE-2026-25755 | jsPDF 对象注入 | 损坏的 JS 字符串 + 注入的 /AA /O 自动动作 | 通过任何查看器的自动回调(jsPDF < 4.2.0) |
| test47.pdf | create_malpdf47() | PDF 2.0 规范 | 关联文件 HTML 嵌入 | 通过目录 /AF + /EF EmbeddedFile 的 HTML | 通过嵌入 HTML 的回调(PDF 2.0 查看器) |
| test48.pdf | create_malpdf48() | XFA 规范 | XFA SOAP 回调 | 带有 initialize 事件的 <submit method="soap"> | SOAP HTTP 请求(Acrobat XFA 引擎) |
%%EOF 标记之后追加新对象/动作。参考:PDF101 内容掩码,Didier Stevensunescape() 编码 — 将 JS 载荷包裹在 eval(unescape("%61%6C%65%72%74...")) 中。参考:corkami PDF 技巧event.target.zoomType == "FitPage" 或全局变量类型检查来检测真实的 Adobe Reader。参考:corkami PDF 技巧