如何在网站文件上传环节阻止可引发PDF阅读器跨站脚本(XSS)攻击的恶意PDF文件
如何拦截带恶意JavaScript的PDF文件上传?
你提到的这种PDF是利用了PDF标准内置的JavaScript执行能力发起攻击的——就像你贴的代码里那样,通过文档打开时触发的动作注解(/AA)执行恶意脚本,这类文件一旦被用户在支持PDF JS的阅读器里打开,就会带来XSS风险。下面分享几个在上传环节就能有效拦截/处理这类恶意文件的方案:
1. 扫描PDF内容,移除或拦截JavaScript相关代码
这是最直接的方式,用服务器端的PDF解析工具检查上传文件的内容,一旦发现恶意脚本相关的标记就拒绝上传,或者自动清理:
- 核心检查点:PDF对象中的
/JavaScript、/AA(动作注解)、/JS(脚本内容)这些关键字——正常的静态PDF不会包含这些项。 - 可以用成熟的PDF处理库实现,比如Python的PyPDF2、Java的iText,或者命令行工具PDFtk。举个简单的Python示例思路:
from PyPDF2 import PdfReader, PdfWriter def check_and_clean_pdf(file_stream): reader = PdfReader(file_stream) has_malicious_js = False writer = PdfWriter() for page in reader.pages: # 检查并移除页面打开时的动作脚本 if "/AA" in page: has_malicious_js = True del page["/AA"] # 移除页面内的独立脚本对象 if "/JS" in page: has_malicious_js = True del page["/JS"] writer.add_page(page) if has_malicious_js: # 这里可以选择拒绝上传,或者返回清理后的PDF return {"status": "blocked", "reason": "包含恶意JavaScript"} return {"status": "allowed", "pdf": writer}
- 注意:一定要在服务器端做这个检查,客户端验证很容易被绕过。
2. 将PDF转换为纯静态格式
如果你的业务不需要PDF的交互功能,可以直接把上传的PDF转换成完全静态的版本,彻底剥离所有脚本和交互元素:
- 实现方式:用无头浏览器(比如Chrome Headless)将PDF渲染成图片,再重新打包成PDF;或者用工具将PDF转为PostScript格式再转回PDF——这个过程会自动丢弃所有动态脚本。
- 好处是从根源上消除了JavaScript执行的可能,安全性拉满;缺点是会丢失原PDF的表单、跳转等交互功能,适合只需要展示静态内容的场景。
3. 验证PDF文件结构的合规性
恶意PDF往往会构造异常的文件结构来绕过检测,你可以在上传时检查PDF的基础结构:
- 验证xref(交叉引用表)和trailer(trailer字典)是否符合PDF标准,拒绝结构异常的文件。
- 限制PDF的文件大小,避免超大的恶意构造文件占用服务器资源。
4. 补充:上传后的安全访问策略
即使上传环节漏过了恶意文件,也要做好后续防护:
- 强制让用户下载PDF,而不是在浏览器中直接打开(很多浏览器默认支持PDF JS执行)。
- 如果需要在线展示PDF,使用禁用了JavaScript的开源PDF查看器(比如PDF.js的安全配置版本)来渲染内容。
对你提供的恶意PDF代码的解析
你贴的这段PDF代码里,核心的恶意逻辑在第3个对象里:
<< /AA << /O << /JS ( try { app.alert("XSS") } catch (e) { app.alert(e.message); } ) /S /JavaScript >> >>
其中:
/AA代表动作注解(Action Annotation),是PDF里用来绑定触发动作的标记;/O表示这个动作在文档打开时触发;/JS后面的括号里就是要执行的JavaScript代码,这里只是弹出"XSS"提示,实际攻击中会换成窃取Cookie、跳转恶意网站等操作。
内容的提问来源于stack exchange,提问作者Spooky
相关产品推荐
相关产品推荐

