File Upload Vulnerabilities
What are file upload vulnerabilities?
Servers allow users to upload files to their filesystem without sufficiently validating:
Type
Content
Size
What is the impact of file upload vulnerabilities?
The impact depends on which aspect of the file the website fails to validate properly (size, type, contents) and the restrictions imposed on the file once uploaded.
If the server is misconfigured and allows files with extensions such as .php or .jsp to execute, an attacker can upload a web shell and gain full control of the server.
Improper validation can allow an attacker to overwrite critical files:
By uploading a file with the same name.
If the server is vulnerable to directory traversal, the attacker can upload files to unanticipated locations.
If the server doesn't check file size thresholds, an attacker can cause a denial of service by filling available disk space.
How do file upload vulnerabilities arise?
Developer implementation flaws that are easily bypassed:
Blacklisting dangerous file types but failing to account for parsing discrepancies.
Not checking file extensions or omitting obscure file types.
Websites may attempt to check file type by verifying properties that can be manipulated by an attacker (e.g., with Burp Repeater).
Inconsistent application of validation across hosts and directories.
How do web servers handle requests for static files?
Historically, websites consisted mostly of static files. Today many sites are dynamic, but static-file handling is still fundamental:
The server parses the path in the request to identify the file extension.
It maps the extension to a MIME type using preconfigured mappings.
If the file is non-executable (image, static HTML), the server typically sends the file content to the client.
If the file is executable (PHP) and the server is configured to execute that type:
The server runs the script, possibly assigning variables from headers/parameters, and returns the resulting output.
If the file is executable but the server is not configured to execute it:
The server may respond with an error or serve the file content as plain text. This misconfiguration can leak source code and other sensitive information.
Exploiting unrestricted file upload to deploy a web shell
A web shell is a malicious script that lets an attacker execute arbitrary commands on a remote web server via HTTP requests.
With a web shell an attacker can:
Read and write arbitrary files
Exfiltrate sensitive data
Pivot to other systems
Example PHP web shell snippet to read a file:
Once uploaded and executed, this returns the target file's contents in the response.
Lab: Remote code execution via web shell upload
Analysis / Recon
Login while proxying traffic through BURP with credentials
wiener:peter.Upload an arbitrary image; the avatar is displayed on the account page.
In Burp: Proxy > HTTP history. Filter by MIME type "images" so you can find the GET request that fetched the avatar:
Example:
GET /files/avatars/<...>
Send that GET request to Burp Repeater.
Attack
Create a file
exploit.phpcontaining:
Use the avatar upload function to upload this PHP file; confirm you receive a 200 response.
In Burp Repeater, change the path to point to your uploaded PHP file:
Send the request. The server executes the script and returns the secret file contents in the response.
Other example web shell:
Request example:
Exploiting flawed validation of file uploads
Flaws in defenses often allow bypasses:
The browser sends file uploads as multipart/form-data. Parts include Content-Disposition and Content-Type headers.
If the server trusts the Content-Type header or filename without further validation, an attacker can tamper with these fields.
Tools like Burp Repeater make it straightforward to modify request fields and bypass naive checks.
Example multipart/form-data snippet:
Lab: Web shell upload via Content-Type restriction bypass
Attack
Attempt to upload
exploit.phpas profile_picture; the site only allows jpeg/png.In Burp, find the
POST /your-account/<exploit.php>request and send it to Repeater.Change the
Content-Typeheader toimage/jpeg.Send the request; the file uploads successfully.
Fetch the file via:
GET /files/<path-to-your-image>and replace withexploit.php.
The response contains customers' credit card information.
Preventing file execution in user-accessible directories
Don't allow dangerous files to be uploaded into directories that can execute them.
Configure the server so it only executes scripts for file types explicitly configured for execution.
If execution is prevented, return uploaded script contents as plain text (which may leak source code but prevents execution).
Example response serving PHP as text/plain:
Different directories may have different configurations. Uploading to a directory with relaxed rules may allow execution.
Note: web servers use the
Filenamefield inmultipart/form-datarequests to determine where to save uploaded files.
Lab: Web shell upload via path traversal
Attack
In Repeater, replace the name of your image with
exploit.phpand send the GET request. The server responds with the PHP file contents as plain text.In Proxy history, send the
POST /my-account/imagerequest to Repeater.In the multipart body, change the Content-Disposition filename to include directory traversal:
Server strips traversal sequences and uploads as
image/exploit.php.
Note: A domain can point to different servers (reverse proxies, load balancers). Your requests may be handled by different back-end servers with different configurations.
Insufficient blacklisting of dangerous file types
Blacklisting extensions (e.g.,
.PHP) is flawed—it's impossible to block every executable extension.Bypasses may use lesser-known executable extensions like
.php5or.shtml.
Overriding the server configuration
Servers only execute files when configured to do so (e.g., Apache with mod_php).
Many servers allow directory-specific configuration files (e.g.,
.htaccessfor Apache,web.configfor IIS) to override global settings.If you can upload such a configuration file, you can map an arbitrary extension to an executable MIME type, causing the server to execute files with that extension.
Example IIS staticContent directive:
Lab: Web shell upload via extension blacklist bypass
Obfuscating file extensions
Even robust blacklists can be bypassed via obfuscation techniques:
Techniques:
Multiple extensions:
exploit.php.jpgmay be interpreted as PHP or JPG.Trailing characters:
exploit.php.— some components strip trailing dots/whitespace.URL encoding (or double encoding):
exploit%2Ephp.Semicolons or URL-encoded null bytes:
Exploit.asp;.jpgorExploit.asp%00.jpg.Multibyte Unicode tricks that get normalized/converted differently between validation and OS-level path handling.
Note: Case-sensitivity issues (e.g., exploit.pHp) can bypass checks that are case-sensitive.
Lab: Web shell upload via obfuscated file extension
Flawed validation of the file's contents
More secure servers verify that file content matches the expected format:
For images: dimensions, magic bytes (JPEG begins with FF D8 FF).
This is robust but not foolproof: attackers can create polyglot files (e.g., a valid JPEG with PHP code in metadata) using tools like ExifTool.
Lab: Remote code execution via polyglot web shell upload
Exploiting file upload race conditions
Secure frameworks typically use a temporary sandboxed directory and randomized filenames, validate the temporary file, and only move it to final destination once safe.
Developer-implemented uploads that deviate from this can introduce race conditions:
Example flawed flow: move file to final location first, then run antivirus and validation; if validation fails, delete the file. The short window between upload and deletion can be exploited.
Example vulnerable PHP snippet:
This race window can often be exploited by sending the POST followed quickly by GET requests (e.g., via Burp Repeater or Turbo Intruder).
Lab: Web shell upload via race condition
Example Turbo Intruder template:
Race condition in URL-based file uploads
Upload-by-URL flows require the server to fetch remote files and often use temporary directories and names.
If temporary directory names are predictable (e.g., PHP uniqid) they can be brute-forced.
Increasing processing time (large files, chunked uploads) lengthens the window for brute-force or race exploitation.
Attackers may upload large files with payload at start and padding to increase processing time.
Exploiting file upload vulnerabilities without remote code execution
Uploading malicious client-side scripts:
Upload HTML or SVG with tags to create stored XSS if uploaded files are served same-origin.
Exploiting parsing vulnerabilities:
Upload XML-based files (e.g., .doc, .xls) and attempt XXE or parser-specific exploits.
Uploading Files using PUT method
Some servers support HTTP PUT; if defenses are absent, PUT can allow file uploads even without a web interface.
Example:
Tip: Send OPTIONS requests to endpoints to check supported methods, including PUT.
How to prevent File Upload Vulnerabilities
Prefer whitelisting permitted extensions (allow-list) instead of blacklisting.
Filenames must not contain substrings that can be interpreted as directory traversal (
../).Rename uploaded files to avoid collisions and predictable names.
Do not move files into permanent filesystem locations until they are fully validated.
Use established frameworks and libraries for handling uploads and validation.
Apply strict directory-level configuration to prevent execution in upload directories (e.g., disable script execution).
Validate both filename and file contents; canonicalize before validation.
Enforce file size limits and quotas to prevent disk-filling DoS.
Avoid trusting client-controlled headers (Content-Type, filename); verify server-side using robust techniques.
Ensure directory-specific configuration files (e.g., .htaccess, web.config) cannot be uploaded or are ignored in upload directories.
Notes and hints
Blacklisting is fundamentally brittle—use allow-lists.
Always validate on the server side; client-side checks are insufficient.
Be aware of per-directory server configuration and possible overrides.