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
相关产品推荐
相关产品推荐

