You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Angular与.NET Core的PDF上传防XSS:拒绝含嵌入式JavaScript的文件

如何在Angular+.NET Core应用中拦截含嵌入式JavaScript的PDF文件

要防范PDF中的嵌入式JS引发的XSS攻击,得从客户端初步拦截+服务端严格校验双管齐下,同时配合后续查看环节的防护,以下是具体实现方案:

一、Angular客户端初步校验(辅助,不能替代服务端)

客户端可以提前拦截明显含JS的PDF,减少无效请求。这里用pdf-lib库解析PDF内容:

  1. 安装依赖:
npm install @pdf-lib/core
  1. 上传组件中添加校验逻辑:
import { PDFDocument } from '@pdf-lib/core';

// 检查PDF是否包含嵌入式JS
async function hasEmbeddedJavaScript(file: File): Promise<boolean> {
  try {
    const arrayBuffer = await file.arrayBuffer();
    const pdfDoc = await PDFDocument.load(arrayBuffer);
    
    // 检查全局JavaScript字典
    const rootDict = pdfDoc.context.trailerInfo.get('Root');
    const hasGlobalJS = rootDict?.get('Names')?.get('JavaScript') !== undefined;
    
    // 检查表单字段的JS动作(比如按钮点击脚本)
    let hasFieldJS = false;
    const acroForm = rootDict?.get('AcroForm');
    if (acroForm) {
      const fields = acroForm.get('Fields');
      if (fields) {
        for (const field of fields.array) {
          const actions = field.get('AA');
          if (actions && actions.get('MouseUp')?.get('JS')) {
            hasFieldJS = true;
            break;
          }
        }
      }
    }
    
    return hasGlobalJS || hasFieldJS;
  } catch (err) {
    // 解析失败的PDF直接判定为可疑
    return true;
  }
}

// 上传触发逻辑
async function handleUpload(event: Event) {
  const file = (event.target as HTMLInputElement).files?.[0];
  if (!file) return;
  
  const isInvalid = await hasEmbeddedJavaScript(file);
  if (isInvalid) {
    alert('该PDF包含嵌入式JavaScript,禁止上传');
    return;
  }
  
  // 执行正常上传流程
}

二、.NET Core服务端严格校验(核心防护)

客户端校验可被篡改,必须在服务端做最终拦截。推荐用iText7(支持.NET Core的PDF处理库)检测JS:

  1. 安装NuGet包:
dotnet add package iText7
  1. 上传接口中添加校验逻辑:
using iText.Kernel.Pdf;

public async Task<IActionResult> UploadPdf(IFormFile file)
{
    if (file == null || file.Length == 0)
        return BadRequest("请选择要上传的文件");
    
    // 校验文件扩展名(辅助,优先检查实际内容)
    var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
    if (ext != ".pdf")
        return BadRequest("仅支持PDF格式文件");
    
    bool containsJavaScript = false;
    using (var pdfReader = new PdfReader(file.OpenReadStream()))
    {
        using var pdfDoc = new PdfDocument(pdfReader);
        var catalog = pdfDoc.GetCatalog().GetPdfObject();
        
        // 检查全局JavaScript字典
        var namesDict = catalog.GetAsDictionary(PdfName.Names);
        if (namesDict != null && namesDict.GetAsDictionary(PdfName.JavaScript)?.Size > 0)
        {
            containsJavaScript = true;
        }
        
        // 检查表单字段的JS动作
        var acroForm = catalog.GetAsDictionary(PdfName.AcroForm);
        if (acroForm != null)
        {
            var fields = acroForm.GetAsArray(PdfName.Fields);
            if (fields != null)
            {
                foreach (PdfObject fieldObj in fields)
                {
                    var field = (PdfDictionary)fieldObj;
                    var actionDict = field.GetAsDictionary(PdfName.AA);
                    if (actionDict != null)
                    {
                        var mouseUpAction = actionDict.GetAsDictionary(PdfName.MouseUp);
                        if (mouseUpAction != null && mouseUpAction.Get(PdfName.JS) != null)
                        {
                            containsJavaScript = true;
                            break;
                        }
                    }
                }
            }
        }
    }
    
    if (containsJavaScript)
        return BadRequest("该PDF包含嵌入式JavaScript,禁止上传");
    
    // 执行文件存储等后续逻辑
    return Ok("上传成功");
}

三、额外防护措施

  1. 存储与分发:

    • 上传后的PDF重命名为随机字符串,避免文件名注入风险
    • 响应时强制设置Content-Type: application/pdf,禁止浏览器自动执行未知内容
    • 用沙箱化的<iframe>加载PDF:
      <iframe src="/files/xxx.pdf" sandbox="allow-same-origin allow-top-navigation"></iframe>
      
  2. 查看环节:

    • 使用无JS支持的PDF查看组件,或配置浏览器PDF查看器禁用JavaScript
    • 严格控制查看页面的权限,禁止用户执行自定义脚本

内容的提问来源于stack exchange,提问作者Sarahbe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 08:29:59