Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type File Upload Vulnerabilities
Difficulty Apprentice
Objective Bypass Content-Type validation on the avatar upload function to upload a PHP web shell and read /home/carlos/secret

Web Shell Upload via Content-Type Restriction Bypass

Uploading tetoshell.php directly this time got rejected:

Screenshot
Sorry, file type application/x-php is not allowed
Only image/jpeg and image/png are allowed

The error message already reveals what's being checked: the Content-Type header in the multipart upload request. That value is set by the browser based on the file extension — which means it's client-controlled and trivially modifiable. Validating Content-Type alone is security theater.

I intercepted the upload in Burp. The relevant part of the multipart body:

Screenshot

Changed Content-Type: application/x-php to Content-Type: image/jpeg:

Screenshot
Screenshot

The server's validation saw image/jpeg and accepted the file — the actual content (PHP code) went unchecked. The .php extension stayed intact, so the file still gets interpreted as PHP when requested. The file extension is what actually determines execution: both the MIME type check and the extension check need to happen server-side, and on the actual file contents — not the headers. A proper implementation reads the magic bytes (JPEG files start with \xFF\xD8\xFF) rather than trusting anything client-supplied.

/files/avatars/tetoshell.php?cmd=whoami

Returns carlos. RCE confirmed.

/files/avatars/tetoshell.php?cmd=cat /home/carlos/secret
Screenshot

Secret extracted. Submitting it:

Screenshot

Lab solved

Resources