File Upload Content Type and MIME Type Bypass Vulnerabilities

Critical Risk File Upload & Path Traversal
file-uploadmime-typecontent-typebypassvalidationdouble-extension

What it is

A critical vulnerability where attackers circumvent file upload restrictions by manipulating MIME types, file extensions, or content headers. Applications that rely solely on client-provided content types or basic extension checking can be bypassed, allowing malicious files to be uploaded and potentially executed, leading to remote code execution or other security compromises.

// VULNERABLE: Trusting client MIME type
const multer = require('multer');

const upload = multer({
  storage: multer.diskStorage({
    destination: './uploads/',
    filename: (req, file, cb) => {
      // VULNERABLE: Using original filename
      cb(null, file.originalname);
    }
  }),
  fileFilter: (req, file, cb) => {
    // VULNERABLE: Checking client-provided MIME type
    const allowed = ['image/jpeg', 'image/png'];
    if (allowed.includes(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error('Invalid type'), false);
    }
  }
});

app.post('/upload', upload.single('file'), (req, res) => {
  res.json({ url: `/uploads/${req.file.filename}` });
});

// Attacker uploads shell.php with Content-Type: image/jpeg
// File is saved and executed when accessed
// SECURE: Server-side content validation
const multer = require('multer');
const { fileTypeFromBuffer } = require('file-type');
const crypto = require('crypto');

const upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 5 * 1024 * 1024 }
});

app.post('/upload', upload.single('file'), async (req, res) => {
  try {
    // SECURE: Detect actual file type from content
    const fileType = await fileTypeFromBuffer(req.file.buffer);
    
    const allowedTypes = ['image/jpeg', 'image/png'];
    if (!fileType || !allowedTypes.includes(fileType.mime)) {
      return res.status(400).json({ error: 'Invalid file type' });
    }
    
    // SECURE: Generate random filename
    const filename = crypto.randomBytes(16).toString('hex') + 
                    fileType.ext;
    
    // SECURE: Store outside web root
    const uploadDir = path.join(__dirname, '../secure_uploads');
    await fs.promises.writeFile(
      path.join(uploadDir, filename),
      req.file.buffer,
      { mode: 0o600 }
    );
    
    res.json({ fileId: filename });
  } catch (error) {
    res.status(500).json({ error: 'Upload failed' });
  }
});

💡 Why This Fix Works

The vulnerable code trusts the client-provided MIME type in file.mimetype and uses the original filename, allowing attackers to upload malicious files by spoofing the Content-Type header. The secure version detects the actual file type by analyzing file content, generates random filenames, and stores files outside the web root with restricted permissions.

Why it happens

Applications rely solely on the Content-Type header sent by clients to validate uploaded files. Attackers can easily manipulate this header to bypass restrictions, uploading malicious executable files while claiming they're images or documents.

Root causes

Trusting Client-Provided Content-Type

Applications rely solely on the Content-Type header sent by clients to validate uploaded files. Attackers can easily manipulate this header to bypass restrictions, uploading malicious executable files while claiming they're images or documents.

Insufficient Extension Validation

File upload validation uses basic extension checking that can be bypassed with double extensions (e.g., malicious.php.jpg) or null byte injection (malicious.php%00.jpg). Simple blacklists of dangerous extensions are incomplete and easily circumvented.

Missing Magic Byte Verification

No server-side validation of file magic bytes (file signatures) to verify actual file types. Applications don't inspect file content structure, allowing attackers to upload polyglot files that are valid as multiple file types simultaneously.

Web Server Misconfiguration

Web servers (Apache, Nginx, IIS) misconfigured to execute files with multiple extensions or unexpected MIME types. Servers may interpret .php.jpg as PHP or allow execution of files in upload directories through improper handler configuration.

Web-Accessible Upload Directories

Uploaded files stored in directories directly accessible via HTTP requests. When combined with execution permissions or content-type misconfigurations, this allows attackers to access and execute uploaded malicious scripts through direct URLs.

Fixes

1

Validate Files Using Magic Bytes

Implement server-side file type validation by inspecting magic bytes (file signatures) at the beginning of uploaded files. Use libraries like Apache Tika, python-magic, or file-type to verify actual file content matches expected types, rejecting files that don't match allowed signatures.

2

Apply Multiple Validation Layers

Implement defense-in-depth with multiple validation layers: magic byte verification, format-specific parsers (ImageMagick for images, PDFBox for PDFs), file size limits, and extension allowlists. Parse files completely to ensure they're well-formed and don't contain embedded malicious content.

3

Store Files Outside Web Root

Store all uploaded files in directories outside the web server's document root where they cannot be directly accessed via HTTP URLs. Serve files through application controllers that enforce authentication and authorization, with proper Content-Disposition headers.

4

Disable Script Execution in Upload Directories

Configure web servers to never execute scripts in upload directories using .htaccess (Apache), nginx configuration, or IIS web.config. Set appropriate MIME types, disable PHP/CGI handlers, and ensure only static file serving is allowed in these directories.

5

Re-encode Files to Strip Malicious Content

For image and document uploads, re-encode files using trusted libraries to strip metadata, embedded scripts, and potential malicious payloads. Use ImageMagick or similar tools to convert images to sanitized versions, removing EXIF data and ensuring only legitimate content remains.

Detect This Vulnerability in Your Code

Sourcery automatically identifies file upload content type and mime type bypass vulnerabilities and many other security issues in your codebase.