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

Fortify扫描C# PDF下载代码标记反射型XSS问题求解

解决Fortify标记的PDF下载反射型XSS问题

你当前用contentType.Contains("application/pdf")的校验太宽松,Fortify会判定攻击者可构造带额外恶意参数的Content-Type(比如application/pdf; <script>...</script>)绕过校验,再加上仅依赖Content-Type而非文件本身特征验证,就会被标记为风险点。以下是具体解决步骤:

  • 精确校验Content-Type
    放弃Contains,改用精确匹配(忽略大小写避免格式问题):

    if (string.Equals(contentType, "application/pdf", StringComparison.OrdinalIgnoreCase))
    {
        // 后续下载逻辑
    }
    

    这种方式能彻底杜绝带额外参数的恶意Content-Type被放行。

  • 验证PDF文件的实际内容
    Content-Type可被篡改,必须校验文件本身的特征。PDF文件开头固定为%PDF-,读取文件流前5个字节验证:

    bool IsValidPdf(Stream fileStream)
    {
        if (fileStream == null || fileStream.Length < 5)
            return false;
        
        fileStream.Position = 0;
        byte[] headerBytes = new byte[5];
        fileStream.Read(headerBytes, 0, 5);
        string header = Encoding.ASCII.GetString(headerBytes);
        
        // 重置流位置,不影响后续读取
        fileStream.Position = 0;
        return header.StartsWith("%PDF-");
    }
    

    调用该方法确认是真实PDF后,再执行下载逻辑。

  • 安全处理下载文件名
    如果下载时指定文件名,需过滤或编码恶意字符(比如<>"&等):

    // 方式1:URL编码
    string safeFileName = HttpUtility.UrlEncode(unsafeFileName).Replace("+", "%20");
    // 方式2:直接过滤特殊字符
    safeFileName = Regex.Replace(unsafeFileName, @"[^\w\d\.\-_]", "");
    

    设置响应头时用处理后的文件名,同时加上attachment强制浏览器下载而非内嵌打开:

    Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{safeFileName}\"");
    
  • 清理响应中的用户可控内容
    如果页面或响应中会显示文件名、下载状态等用户可控内容,必须先做HTML编码再输出:

    string displayFileName = HttpUtility.HtmlEncode(safeFileName);
    // 将displayFileName输出到页面
    

    防止攻击者通过构造恶意文件名触发页面XSS。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:13:11