Page cover
githubEdit

file-plusUnrestricted File Upload

chevron-rightFilename Parameter Confusion (Busboy/OpenResty)hashtag

The validator and the storage mechanism look at different parameters in the Content-Disposition header.

  • Validator checks: filename

  • Storage uses: filename*

Exploit
Content-Disposition: form-data; name="file"; filename="image.png"; filename*=utf-8''attack.svg
chevron-rightStandard Extension Obfuscationhashtag
  • There are normally three ways a web server will check for valid file types by comparing them to an allow- or deny-list:

circle-info

Double extensions

circle-info

Null byte injection

circle-info

Alternative Executable Extensions

chevron-rightBypassing MIME Type Checkshashtag

The application checks the Content-Type header in the request, not the actual file content.

Intercept the request and change the header to an allowed type.

chevron-rightBypassing Content Checkshashtag

The server only checks the start of the file.

Create a Polyglot File by combining the Magic Bytes of an image with the code of a webshell.

chevron-rightSVG XSS Payloadshashtag
circle-info

Accessing Internal Uploads (Localhost SSRF)

Even if the file upload is successful, the file may be inaccessible via the public URL because the application runs on an internal port or the directory isn't mapped to the public web root.

However, leveraging server-side features like admin bots or PDF generators to fetch the file via localhost is essential not just for access, but to execute the payload within a privileged context.

Since these internal features operate from the server's environment, they can bypass network segmentation and access sensitive resources, such as admin panels or internal APIs.

Last updated