Insecure File Upload Code Review Guide
Table of Contents
Introduction
Insecure file upload vulnerabilities occur when applications allow users to upload files without proper validation, potentially leading to remote code execution, data breaches, and complete system compromise. These vulnerabilities are particularly dangerous because they can provide attackers with direct access to the server filesystem.
Unlike other web vulnerabilities that exploit application logic, file upload attacks often target the underlying server infrastructure. A successful file upload attack can result in the attacker gaining shell access, installing malware, or using the compromised server as a launching point for further attacks.
File Upload Attack Flow
malicious.php.jpg
Weak validation
File stored
Code execution
Data access
System takeover
Critical Impact
File upload vulnerabilities consistently rank among the most dangerous web application security risks because they often lead to immediate remote code execution with the privileges of the web application.
Real-World Scenario
Imagine you're reviewing a user profile feature where users can upload avatar images. The developer implemented basic file type checking based on file extensions. Here's what the vulnerable code might look like:
Vulnerable PHP Code
1// Vulnerable PHP code
2$allowed_extensions = array('jpg', 'jpeg', 'png', 'gif');
3$filename = $_FILES['avatar']['name'];
4$file_extension = pathinfo($filename, PATHINFO_EXTENSION);
5
6if (in_array(strtolower($file_extension), $allowed_extensions)) {
7 $upload_path = 'uploads/' . $filename;
8 move_uploaded_file($_FILES['avatar']['tmp_name'], $upload_path);
9 echo "File uploaded successfully!";
10} else {
11 echo "Invalid file type!";
12}
An attacker could exploit this by uploading a file named malicious.php.jpg
containing PHP code. The server might execute the PHP code when the file is accessed, despite the .jpg extension.
What makes the above code snippet vulnerable?
Understanding File Upload Risks
File upload vulnerabilities arise from insufficient validation of uploaded files. Understanding the various attack vectors helps you identify potential security issues during code review.
Common File Upload Attack Vectors
Attack Type | Description | Impact |
---|---|---|
Executable Upload | Uploading scripts (PHP, JSP, ASP) that get executed | Remote Code Execution |
Path Traversal | Using ../ in filenames to write outside upload directory | Arbitrary File Write |
Content-Type Bypass | Manipulating MIME type headers | Filter Evasion |
Double Extension | Files like malicious.php.jpg | Execution Bypass |
Null Byte Injection | Using %00 to truncate filenames | Extension Bypass |
Polyglot Files | Files valid as multiple formats | Complex Attacks |
Server Configuration Impact
The risk level depends heavily on server configuration. Apache servers with mod_php might execute .php files regardless of additional extensions, while nginx with strict configuration might be safer.
Finding Upload Vulnerabilities
During code review, look for file upload functionality and examine how uploaded files are validated, stored, and accessed. Focus on the validation logic and file handling mechanisms.
Common Vulnerable Patterns
1// Node.js/Express vulnerable patterns
2
3// DANGEROUS: Only checking file extension
4if (filename.endsWith('.jpg')) {
5 // Upload file
6}
7
8// DANGEROUS: Trusting client-side MIME type
9if (req.file.mimetype === 'image/jpeg') {
10 // Upload file
11}
12
13// DANGEROUS: No file size limits
14app.post('/upload', upload.single('file'), (req, res) => {
15 // No validation at all
16 res.send('File uploaded');
17});
18
19// DANGEROUS: Predictable upload paths
20const uploadPath = './uploads/' + req.file.originalname;
Which validation method is the most secure for image uploads?
Identifying Input Sources
File upload vulnerabilities can originate from various input sources. During code review, identify all places where files can enter your application:
- Web Forms: HTML file input elements, drag-and-drop upload zones, multi-file upload interfaces
- API Endpoints: REST API file uploads, GraphQL file uploads, multipart/form-data submissions
- Email Attachments: Processing email attachments, automated file extraction from emails
- FTP/SFTP: File transfers via FTP, SFTP uploads, automated file monitoring
- Third-party Integrations: Files from cloud storage APIs, webhook file submissions, partner system integrations
- Content Management: CMS file uploads, document management systems, media libraries
- Import Functions: CSV/Excel imports, configuration file uploads, backup file restoration
Example: Multiple Upload Sources
1from flask import Flask, request
2import requests
3
4def handle_uploads():
5 # Web form upload - direct user input
6 if 'file' in request.files:
7 uploaded_file = request.files['file']
8
9 # API upload - JSON with base64 file
10 if request.json and 'file_data' in request.json:
11 file_data = request.json['file_data']
12
13 # Third-party webhook - external file URL
14 if 'file_url' in request.json:
15 response = requests.get(request.json['file_url'])
16 file_content = response.content
17
18 # Email attachment processing
19 email_attachments = process_email_attachments()
20
21 # ALL these inputs could be malicious
22 # Each needs proper validation
Tracing File Flow
Understanding how files flow through your application is crucial for identifying security gaps. Trace the complete path from upload to storage and access.
File Flow Analysis
1@RestController
2public class FileUploadController {
3
4 // 1. ENTRY POINT: File enters via HTTP request
5 @PostMapping("/upload")
6 public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) {
7
8 // 2. VALIDATION: Check file properties
9 if (!isValidFile(file)) { // Validation logic
10 return ResponseEntity.badRequest().body("Invalid file");
11 }
12
13 // 3. PROCESSING: Transform or analyze file
14 String processedContent = processFile(file); // Processing step
15
16 // 4. STORAGE: Save to filesystem/database
17 String filePath = saveFile(file); // Storage location
18
19 // 5. ACCESS: How will file be accessed later?
20 return ResponseEntity.ok("/files/" + filePath); // Public access?
21 }
22
23 // Critical: Where and how is the file served back to users?
24 @GetMapping("/files/{filename}")
25 public ResponseEntity<Resource> serveFile(@PathVariable String filename) {
26 // DANGER: Direct file serving without validation
27 Resource file = loadFileAsResource(filename);
28 return ResponseEntity.ok(file);
29 }
30}
Critical Analysis Points
Pay special attention to: 1) Where files are stored (web-accessible directory?), 2) How files are served back to users, 3) Whether the web server can execute uploaded files, 4) File naming conventions and potential conflicts.