Lab 14: File Upload Vulnerabilities

Objective

Attack a live file upload endpoint from Kali Linux and bypass its defences using multiple techniques:

  1. No-validation upload — upload a PHP webshell directly (shell.php) with zero checks

  2. Double extension bypass — fool an extension allowlist with shell.php.jpg

  3. Polyglot file — craft a file with valid JPEG magic bytes that contains PHP code

  4. SVG with embedded XSS — bypass image-only filters with a malicious SVG

  5. Path traversal via filename — read arbitrary files using ../ in the filename parameter

  6. Enumerate uploads — discover all uploaded files including other attackers' webshells

All attacks run from Kali against a live Flask API — real file bytes saved server-side, real traversal paths resolved.


Background

File upload vulnerabilities have been behind some of the most severe breaches in history. An unrestricted file upload is effectively Remote Code Execution — the attacker uploads a webshell, then executes arbitrary OS commands through it.

Real-world examples:

  • 2021 GitLab (CVE-2021-22205) — ExifTool processed uploaded images without validation; a crafted DjVu file triggered RCE on 50,000+ servers. CVSS 10.0.

  • 2023 MOVEit Transfer (CVE-2023-34362) — SQL injection in file upload handler; the Cl0p ransomware group stole data from 2,000+ organizations including US government agencies.

  • WordPress file upload bypassshell.php5, shell.phtml, shell.pHp all execute as PHP on misconfigured servers; shell.php.jpg executes if Apache AddHandler is misconfigured.

OWASP coverage: A03:2021 (Injection — webshell), A04:2021 (Insecure Design)


Architecture

Time

45 minutes

Tools

Tool
Container
Purpose

curl

Kali

Upload files via multipart POST

python3

Kali

Craft polyglot files, automate enumeration

nmap

Kali

Service fingerprinting

gobuster

Kali

Enumerate upload endpoints


Lab Instructions

Step 1: Environment Setup — Launch the Victim Upload Server


Step 2: Launch the Kali Attacker Container

📸 Verified Output:


Step 3: Upload a PHP Webshell — No Validation

📸 Verified Output:

💡 A PHP webshell turns the web server into a remote shell. system($_GET["cmd"]) passes the cmd URL parameter directly to the OS shell and returns the output. In real Apache+PHP deployments, the attacker now has full command execution as the web server user. From there: read /etc/passwd, read config files with DB passwords, establish a reverse shell, pivot to internal services.


Step 4: Double Extension Bypass — shell.php.jpg

📸 Verified Output:


Step 5: Polyglot File — Valid JPEG + PHP Payload

📸 Verified Output:


Step 6: SVG with Embedded XSS

📸 Verified Output:


Step 7: Path Traversal — Read Arbitrary Files

📸 Verified Output:


Step 8: Cleanup


Attack Summary

Phase
Technique
Endpoint
Result

1

PHP webshell, no checks

/api/upload

shell.php saved — RCE on PHP server

2

Double extension

/api/upload-strict

shell.php.jpg bypasses allowlist

3

Polyglot JPEG+PHP

/api/upload-strict

Passes magic byte check, still executable

4

SVG XSS

/api/upload

Stored XSS via "image" upload

5

Path traversal

/api/read?name=../

/etc/passwd and source code read

6

Upload enumeration

/api/files

All uploaded webshells listed


Remediation

Defence
What it prevents

Extension allowlist (last ext only)

Double extension bypass

Magic byte check

Polyglot files disguised as images

Reject SVG

Stored XSS via SVG

Random rename

Webshell execution (can't guess filename to call it)

Store outside web root

Even if webshell is uploaded, it can't be executed via HTTP

Serve via X-Content-Type-Options: nosniff

Browser MIME sniffing attacks

Further Reading

Last updated