当前位置: 首页 > news >正文

PDF-XSS

前言:

PDF文件是一种复杂的文档格式,由一系列对象组成,包括字体、图像、页面内容等。PDF文件支持嵌入JavaScript代码,这使得PDF文件不仅可以显示静态内容,还可以执行动态操作。这种特性被攻击者利用来嵌入恶意脚本代码。

攻击者通过在PDF文件中嵌入恶意JavaScript代码,使得当用户打开该PDF文件时,恶意代码会在用户的浏览器或PDF阅读器中执行。

pdf-xss制作:

python代码如下:

from PyPDF2 import PdfReader, PdfWriter
# 创建一个新的 PDF 文档
output_pdf = PdfWriter()
# 添加一个新页面
page = output_pdf.add_blank_page(width=72, height=72)
# 添加js代码
output_pdf.add_js("app.alert('xss');")
# 将新页面写入到新 PDF 文档中
with open("alert.pdf", "wb") as f:output_pdf.write(f)

执行后会将脚本植入到pdf中,对应的pdf分析

 

当我们打开对应的pdf文件,可以看到弹出了对应的xss对话框

修复:

代码修复也很简单,就是要处理JavaScript方法,对应的处理的点如下

  • 识别并移除/Names/JavaScript结构
  • 处理嵌套字典中的JavaScript
  • 处理数组中的JavaScript动作
  • 递归检查所有可能的位置

对应的java代码如下

package org.example;import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;import java.io.File;
import java.io.IOException;
import java.util.List;public class Main {public static void main(String[] args) {String inputFile = "alert.pdf";String outputFile = "safe-output.pdf";try {removeJavaScript(inputFile, outputFile);System.out.println("PDF中的JavaScript已彻底移除!");} catch (IOException e) {System.err.println("处理失败: " + e.getMessage());}}public static void removeJavaScript(String inputPath, String outputPath) throws IOException {PDDocument document = Loader.loadPDF(new File(inputPath));try {// 1. 处理文档级JavaScriptprocessDocumentLevelJS(document);// 2. 处理页面级JavaScriptprocessPagesJS(document);// 3. 保存处理后的文档document.save(outputPath);} finally {document.close();}}// 处理文档级的JavaScriptprivate static void processDocumentLevelJS(PDDocument document) {// 获取文档目录PDDocumentCatalog catalog = document.getDocumentCatalog();COSDictionary catalogDict = catalog.getCOSObject();// 处理文档开放动作catalog.setOpenAction(null);// 专门处理Names字典中的JavaScriptprocessNamesDictionaryJS(catalogDict);// 移除标准JS和AAremoveDictJavaScript(catalogDict);}// 专门处理Names字典中的JavaScriptprivate static void processNamesDictionaryJS(COSDictionary dict) {if (dict.containsKey(COSName.NAMES)) {COSDictionary namesDict = dict.getCOSDictionary(COSName.NAMES);if (namesDict != null) {// 检查JavaScript字典if (namesDict.containsKey(COSName.JAVA_SCRIPT)) {namesDict.removeItem(COSName.JAVA_SCRIPT);System.out.println("已移除文档级的Named JavaScript字典");// 如果Names字典变空(即没有其他条目了),则移除整个Names字典if (namesDict.size() == 0) { // 修改这里:使用size()==0代替isEmpty()dict.removeItem(COSName.NAMES);}}}}}// 处理页面级JavaScriptprivate static void processPagesJS(PDDocument document) throws IOException {for (PDPage page : document.getPages()) {// 处理页面级JavaScriptCOSDictionary pageDict = page.getCOSObject();removeDictJavaScript(pageDict);// 处理页面注释List<PDAnnotation> annotations = page.getAnnotations();for (PDAnnotation annotation : annotations) {removeAnnotationJavaScript(annotation);}}}// 移除注释中的JavaScriptprivate static void removeAnnotationJavaScript(PDAnnotation annotation) {COSDictionary dict = annotation.getCOSObject();removeDictJavaScript(dict);}// 核心方法:移除COSDictionary中的JavaScriptprivate static void removeDictJavaScript(COSDictionary dict) {// 1. 直接移除所有JavaScript项dict.removeItem(COSName.JS);// 2. 检查并移除标准动作中的JavaScriptif (dict.containsKey(COSName.A)) {COSDictionary actionDict = dict.getCOSDictionary(COSName.A);if (isJavaScriptAction(actionDict)) {dict.removeItem(COSName.A);}}// 3. 检查并移除附加动作中的JavaScriptif (dict.containsKey(COSName.AA)) {COSDictionary aaDict = dict.getCOSDictionary(COSName.AA);removeAllJavaScriptFromDict(aaDict);}// 4. 处理Names字典(针对嵌套的Names字典)processNamesDictionaryJS(dict);}// 检查是否为JavaScript动作private static boolean isJavaScriptAction(COSDictionary actionDict) {// JavaScript动作的标识:/S 为 /JavaScriptreturn COSName.JAVA_SCRIPT.equals(actionDict.getCOSName(COSName.S)) ||actionDict.containsKey(COSName.JS);}// 彻底清除字典中的所有JavaScriptprivate static void removeAllJavaScriptFromDict(COSDictionary dict) {// 遍历所有条目for (COSName key : dict.keySet().toArray(new COSName[0])) {COSBase value = dict.getItem(key);// 1. 直接移除JavaScript项if (value == COSName.JS || key == COSName.JS) {dict.removeItem(key);}// 2. 处理嵌套的JavaScript字典else if (value instanceof COSDictionary) {COSDictionary subDict = (COSDictionary) value;if (isJavaScriptAction(subDict)) {dict.removeItem(key);} else {// 递归处理嵌套字典removeAllJavaScriptFromDict(subDict);}}// 3. 处理数组中的JavaScriptelse if (value instanceof COSArray) {processArrayForJavaScript((COSArray) value);}}}// 处理数组中的JavaScriptprivate static void processArrayForJavaScript(COSArray array) {for (int i = 0; i < array.size(); i++) {COSBase element = array.get(i);if (element instanceof COSDictionary) {COSDictionary dict = (COSDictionary) element;if (isJavaScriptAction(dict)) {array.remove(i); // 从数组中移除JavaScript字典i--; // 调整索引}}}}
}

上述代码具体的执行逻辑如下: 

  1. 完整遍历​:

    • 文档级 (1次)
    • 页面级 (每页1次)
    • 注释级 (每个注释1次)
    • 潜在嵌套结构 (无限递归深度)
  2. 脚本检测​:

    • 检测到JS项的PDF对象:直接移除
    • 检测到A/AA项中的JS动作:移除整个动作项
    • 检测到Names中的JS:移除整个JS子字典
  3. 资源清理​:

    • 移除后的空容器会被清理
    • 只移除脚本相关项,保留其他内容

对应的执行完成的和开始的对比

 统一为1.6版本的pdf格式

如此便可以去除pdf文件中的js脚本代码,后续最好再head中添加

CSP和X-Content-Type-Options:  nosniff

可以进一步防御xss攻击

http://www.lqws.cn/news/487639.html

相关文章:

  • xss利用meta强制跳转 CPS report-uri 报错泄露利用 -- GPN CTF 2025 Free Parking Network 1 2
  • 设计模式 - 抽象工厂
  • Perl 正则表达式
  • Chromium 136 编译指南 macOS篇:编译优化技巧(六)
  • 苹果芯片macOS安装版Homebrew(亲测)
  • “自动化失败归因”测试集-WhoWhen
  • RealSense 相机 | 读取IMU | 解决权限问题 | 提供示例程序
  • 【无刷电机FOC进阶基础准备】【04 clark变换、park变换、等幅值变换】
  • Python Django全功能框架开发秘籍
  • 五分钟了解@ExcelIgnoreUnannotated注解
  • Bug闭环解决之道:主流Bug追踪工具优劣对比
  • 月球上基于分段的全局定位
  • 【BFS】P9126 [USACO23FEB] Moo Route II S|普及+
  • MCU双分区方案,如何优雅地获知当前运行分区?
  • 纯血HarmonyOS5 打造小游戏实践:绘画板(附源文件)
  • 【基础篇-消息队列】——详解 RocketMQ 和 Kafka 的消息模型
  • 7.4.2B+树
  • 红帽全球副总裁曹衡康:开源AI开启企业级应用新纪元
  • 详解HarmonyOS NEXT仓颉开发语言中的全局弹窗
  • Android 中查看数据库内容方式
  • vue-23(创建用于逻辑提取的可重用组合组件)
  • Linux-系统管理
  • Java面试题027:一文深入了解数据库Redis(3)
  • 【Linux指南】文件管理高级操作(复制、移动、查找)
  • 学习Linux进程冻结技术
  • 县城消费市场的调研
  • 微算法科技(NASDAQ:MLGO)研发可信共识算法TCA,解决区块链微服务中的数据一致性与安全挑战
  • 从哈希到挑战响应,密码传输安全解析
  • 基于Qt开发的ModbusTcp主站软件开发教程​——从协议原理到工业级实现
  • python基于微信小程序的广西文化传承系统