XSS_FILE_UPLOAD_CONTENT_DISPOSITION security resource_error ai_generated true

XSS via malicious file upload with Content-Disposition bypass

ID: security/xss-via-malicious-file-upload-with-content-disposition-bypass

Also available as: JSON · Markdown · 中文
88%Fix Rate
82%Confidence
1Evidence
2024-01-20First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
Apache Tomcat 9.0.70 active
Spring Boot 2.7.10 active
Nginx 1.24.0 active
IIS 10.0 active

Root Cause

When a file upload endpoint returns user-supplied filenames in the Content-Disposition header without proper sanitization, an attacker can inject script code that executes in the browser when the file is downloaded.

generic

中文

当文件上传端点在Content-Disposition头中返回用户提供的文件名而未进行适当清理时,攻击者可以注入脚本代码,在下载文件时在浏览器中执行。

Official Documentation

https://owasp.org/www-community/attacks/xss/

Workarounds

  1. 90% success Sanitize the filename by stripping all non-alphanumeric characters except dots and hyphens. Example in Python: import re; safe_filename = re.sub(r'[^a-zA-Z0-9._-]', '', original_filename). Then set Content-Disposition to attachment; filename="safe_filename" and ensure Content-Type is correct.
    Sanitize the filename by stripping all non-alphanumeric characters except dots and hyphens. Example in Python: import re; safe_filename = re.sub(r'[^a-zA-Z0-9._-]', '', original_filename). Then set Content-Disposition to attachment; filename="safe_filename" and ensure Content-Type is correct.
  2. 95% success Use a random UUID as the filename on the server and store the original filename in a database, never returning it in headers. Example: response.setHeader('Content-Disposition', 'attachment; filename="' + uuid + '"');
    Use a random UUID as the filename on the server and store the original filename in a database, never returning it in headers. Example: response.setHeader('Content-Disposition', 'attachment; filename="' + uuid + '"');
  3. 85% success Add Content-Security-Policy header with 'sandbox' directive for file download endpoints to prevent script execution.
    Add Content-Security-Policy header with 'sandbox' directive for file download endpoints to prevent script execution.

中文步骤

  1. Sanitize the filename by stripping all non-alphanumeric characters except dots and hyphens. Example in Python: import re; safe_filename = re.sub(r'[^a-zA-Z0-9._-]', '', original_filename). Then set Content-Disposition to attachment; filename="safe_filename" and ensure Content-Type is correct.
  2. Use a random UUID as the filename on the server and store the original filename in a database, never returning it in headers. Example: response.setHeader('Content-Disposition', 'attachment; filename="' + uuid + '"');
  3. Add Content-Security-Policy header with 'sandbox' directive for file download endpoints to prevent script execution.

Dead Ends

Common approaches that don't work:

  1. 65% fail

    Sanitizing the filename by removing only script tags is insufficient because attackers can use event handlers like onerror or encode characters to bypass filters.

  2. 55% fail

    Setting Content-Type to application/octet-stream does not prevent XSS if the browser sniffs the content type or if the filename contains script that executes on download.

  3. 50% fail

    Using a whitelist of allowed extensions is bypassed if the filename contains script in the parameter string (e.g., file.html?script=alert(1)).