前言:

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.pswp.cn/diannao/88203.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88203.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/88203.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 表关联关系详解

MySQL 表关联关系详解 本文档详细列举了MySQL中常见的表关联关系场景以及对应的SQL语句示例。 1. 一对一关系 (One-to-One) 场景&#xff1a;用户表和用户详情表 一个用户对应一个用户详情通常用于将大表拆分&#xff0c;提高查询性能 -- 创建用户表 CREATE TABLE users (…

kubernetes(k8s)集群部署(超详细)

k8s部署 kubernetes集群图例kubernetes 安装仓库初始化1、创建云主机2、初始化私有仓库kube-master安装1、防火墙相关配置2、配置yum仓库(跳板机)3、安装软件包(master)4、镜像导入私有仓库5、Tab键设置6、安装代理软件包7、配置内核参数8、使用kubeadm部署9、验证安装结果计算…

「Flink」算子主要方法介绍

背景&#xff1a; 上期文章主要讲了Flink项目搭建的一些方法&#xff0c;其中对于数据流的处理很大一部分是通过算子来进行计算和处理的&#xff0c;算子也是Flink中功能非常庞大&#xff0c;且很重要的一部分。 算子介绍&#xff1a; 算子在Flink的开发者文档中是这样介绍的…

3405. 统计恰好有 K 个相等相邻元素的数组数目

3405. 统计恰好有 K 个相等相邻元素的数组数目 给你三个整数 n &#xff0c;m &#xff0c;k 。长度为 n 的 好数组 arr 定义如下&#xff1a; arr 中每个元素都在 闭 区间 [1, m] 中。恰好 有 k 个下标 i &#xff08;其中 1 < i < n&#xff09;满足 arr[i - 1] arr…

Spring AI 项目实战(十):Spring Boot + AI + DeepSeek 构建智能合同分析技术实践(附完整源码)

系列文章 序号文章名称1Spring AI 项目实战(一):Spring AI 核心模块入门2Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码)3Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码)4

impala中时间戳转(DATE)指定格式的字符串

注意i&#xff1a;注意大小写 timestamp\date–>string SELECT now(),from_timestamp(now(),yyyyMMdd);string->timestamp SELECT 20230710,to_timestamp(20230710,yyyyMMdd);日期加减 select 20231201,from_timestamp(date_add(to_timestamp(20231201,yyyyMMdd),1),…

百度下拉框出词技术解密:72小时出下拉词软件原理分享

如何才能刷下拉词&#xff1f;这个问题一直是企业做流量时最纠结的问题&#xff0c;百度下拉词作为百度搜索体验中的一项智能化功能&#xff0c;极大地方便了用户快速完成搜索&#xff0c;也成为了企业在搜索引擎优化&#xff08;SEO&#xff09;策略中的重要流量入口。通过研究…

上海人工智能实验室明珠湖会议首开,解答AI前沿疑问,推进科学智能

在通用人工智能&#xff08;AGI&#xff09;探索如火如荼的当下&#xff0c;如何加速突破&#xff1f;如何凝练关键问题、孕育颠覆性创新&#xff1f;2025年6月13日&#xff0c;上海人工智能实验室主任、首席科学家&#xff0c;清华大学惠妍讲席教授周伯文在首届明珠湖会议&…

BeyondCompare安装(永久免费使用+全网最详细版)

一.下载&#xff1a; 官网下载&#xff08;速度较慢&#xff09;&#xff1a; https://www.scootersoftware.com/download.php 阿里云盘&#xff08;不限速&#xff09; https://www.alipan.com/s/WaG1z54BQ2U 二.安装&#xff08;无脑下一步即可&#xff09; 三.永久免费…

如何用AI开发完整的小程序<7>—让AI微调UI排版

上一节我们介绍了如何让AI修改整体UI视觉效果。 不过有时候AI调整的并不理想&#xff0c;一些UI的布局还是需要微调。 比如已经实现的这个开始页面&#xff0c;我觉得标题太高了&#xff0c;这时候可以自己调&#xff0c;也可以让AI单独调&#xff0c;下面详细介绍。 一、手动…

64-Oracle Redo Log

小伙伴们&#xff0c;关于数据库的redo log相信大家都操作很多次了,且这是OCM考试必考内容。Oracle Redo Log是一种特殊的日志文件&#xff0c;用于完整地记录数据库中所有数据变更的详细信息。当数据库执行插如、更新或删除等更新操作&#xff0c;这些操作并不会立刻写入数据库…

hive集群优化和治理常见的问题答案

Hive 集群优化与治理常见问题答案合集 &#x1f42d;1. Q&#xff1a;Hive中如何优化大表Join操作&#xff1f; A&#xff1a; 使用Map Join&#xff08;小表Join大表时&#xff09;避免Reduce阶段。启用自动Map Join&#xff08;设置hive.auto.convert.jointrue&#xff09;…

C#采集电脑硬件(CPU、GPU、硬盘、内存等)温度和使用状况

这是采集出来的Json&#xff0c;部分电脑&#xff08;特别是笔记本&#xff09;无法获取到&#xff1a; {"HardwareList": [{"Name": "MITX-6999","Type": "主板","Sensors": [],"WmiReport": null}, …

C3新增特性

✅ 一、选择器&#xff08;Selectors&#xff09; 1. 属性选择器 [attr^value]: 匹配属性值以特定字符串开头的元素。[attr$value]: 匹配属性值以特定字符串结尾的元素。[attr*value]: 匹配属性值包含特定字符串的元素。 2. 子元素和兄弟元素选择器 :nth-child(n): 匹配父元…

报错 @import “~element-ui/packages/theme-chalk/src/index“;

报错 import "~element-ui/packages/theme-chalk/src/index"; 具体报错报错原因 具体报错 SassError: Can’t find stylesheet to import. import “~element-ui/packages/theme-chalk/src/index”; src\views\login\theme\element-variables.scss 8:9 root stylesh…

ESLint从入门到实战

引言 作为前端开发者&#xff0c;你是否遇到过这样的情况&#xff1a;团队成员写出的代码风格各异&#xff0c;有人喜欢用分号&#xff0c;有人不用&#xff1b;有人用双引号&#xff0c;有人用单引号&#xff1b;代码评审时总是在纠结这些格式问题而不是业务逻辑&#xff1f;…

vue3实现markdown文档转HTML并可更换样式

vue3实现markdown文档转HTML 安装marked npm install marked<template><!-- 后台可添加样式编辑器 --><div class"markdown-editor" :class"{ fullscreen: isFullscreen, preview-mode: isPreviewMode }"><div class"editor-c…

Temu 实时获取商品动态:一个踩坑后修好的抓数脚本笔记

Temu 作为一个增长迅猛的购物平台&#xff0c;其商品价格、库存等信息&#xff0c;对许多做运营分析的小伙伴来说非常有参考价值。 我在写这个小工具的时候&#xff0c;踩了很多坑&#xff0c;特别记录下来&#xff0c;希望对你有用。 初版代码&#xff1a;想当然的“直接来一下…

【软考高级系统架构论文】论数据分片技术及其应用

论文真题 数据分片就是按照一定的规则,将数据集划分成相互独立、 正交的数据子集,然后将数据子集分布到不同的节点上。通过设计合理的数据分片规则,可将系统中的数据分布在不同的物理数据库中,达到提升应用系统数据处理速度的目的。 请围绕“论数据分片技术及其应用”论题…

VR飞夺泸定桥沉浸式历史再现​

当你戴上 VR 设备开启这场震撼人心的 VR 飞夺泸定桥体验&#xff0c;瞬间就会被拉回到 1935 年那个战火纷飞的 VR 飞夺泸定桥的岁月&#xff0c;置身于泸定桥的西岸 。映入眼帘的是一座由 13 根铁索组成的泸定桥&#xff0c;它横跨在波涛汹涌的大渡河上&#xff0c;桥下江水咆哮…