File Upload Bypass (Content-Type)
Full command arsenal in the cheatsheetMany upload forms "validate" a file's type by looking at the Content-Type header the client sends in the multipart request. The problem is that this value is set by the browser (or by us), not by the real content: changing it to image/png while uploading a .php fools that check and lets you write an executable file to the server (file upload to RCE).
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: image/png
<?php system($_GET['cmd']); ?>If the server only checks the Content-Type (not the final extension, the content or where it lands), the .php ends up in a web-accessible folder and is invoked:
curl 'https://<ip>/uploads/shell.php?cmd=id'It's one of the weakest validations, and it combines with or alternates with other upload bypasses: double extension, null byte, or faking the file signature (magic bytes) when the first bytes are also inspected.
Nuances. A Content-Type passing doesn't guarantee RCE: the file must also be stored with an executable extension and in a path served by the interpreter. If the server renames it, relocates it to a no-execute store or validates the real content, the Content-Type bypass isn't enough.
How to detect it. In the server logs the signature is a multipart request whose declared Content-Type (image/png) does not match the extension or the real file content, followed shortly after by a GET to that same file in the uploads directory. A .php, .jsp or .aspx appearing inside a user image folder is, on its own, an indicator of compromise.
Defence. Don't trust the client Content-Type; validate the real content (server-side MIME by magic bytes), force a safe extension, store outside the webroot and serve it with a handler that doesn't execute.