# [Exploitation/Web] File upload

## Introduction

Les injections de code par envoi de fichier sont redoutables sur les pages web puisqu'elles aboutissent généralement à une execution de commande à distance (**RCE**).

Les sécurités mises en place par les développeurs ne sont parfois pas suffisantes car un tas de paramètres doit être contrôlé avant de permettre l'envoie d'un fichier sur le serveur.

## [![image.png](https://wiki.neopipe.fr/uploads/images/gallery/2023-11/scaled-1680-/Yshimage.png)](https://wiki.neopipe.fr/uploads/images/gallery/2023-11/Yshimage.png)Source

- [Documentation officielle de la fonction PHP basename() ](https://www.php.net/manual/en/function.basename.php)

## Exploits

#### Webshell

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

#### Double extensions

En effet, les formulaires d'envoi de fichiers sont parfois uniquement protégé par un **filtre sur l'extension du fichier**.

Malheureusement, ce filtre est aisément contournable en mettant une **double extension** sur votre fichier.

<span style="text-decoration: underline;">Exemple :</span>

```
payload.php.png
```

Ce type d'attaque fonctionne car le navigateur fait du **Content-Type-Sniffing** sur le fichier pour l'interpreter.

C'est à dire qu'il va l'analyser pour déterminer son type sans se fier à l'**extension** ou au **content-type** de l'en-tête du fichier.

Pour l'exploiter il suffit donc de :

- Créer votre payload au format standard php
- Renommer le fichier de sorte à ajouter l'extension de fichier autorisé (après le *.php*)
- Envoyer le fichier sur le serveur
- Accéder au fichier via l'URL pour exécuter le payload.

#### Type MIME

Une autre protection est le filtre par **type MIME** du fichier envoyé.

Les types MIME définissent le format et le type de contenu d'un fichier, permettant de reconnaître et d'interpréter correctement le contenu des fichiers.

Lors de l'envoi d'un fichier, <span style="text-decoration: underline;">le type MIME est spécifié dans l'entête de la requête</span> via le paramètre **content-type**.

Grâce à des outils comme **Burp**, il est possible de modifier la requête pour modifier ce paramètre et tromper le serveur sur le type de fichier envoyé.

Voici quelques content-type (MIME) qui peuvent vous servir à contourner une protection basée sur le MIME :

- **application/pdf** (utilisé pour les fichiers pdf)
- **text/html** (utilisé pour les fichiers html)
- **application/php** (utilisé pour les fichiers php)
- **image/jpeg** (utilisé pour les fichiers jpeg/jpg)
- **application/png** (utilisé pour les fichiers png)

#### Null byte

Lorsque le serveur se base sur l'**extension du fichier** et sur le **MIME** du fichier il semble impossible de le duper.

Pourtant, il existe une dernière technique très puissante qui exploite une faiblesse de la fonction **basename()** utilisé en **php** pour <span style="text-decoration: underline;">obtenir le nom du fichier</span> (ainsi que son extension).

Cette fonction étant codée en **langage C**, elle est sensible aux caractères **ASCII** dont le fameux **null byte**, aussi appelé caractère zéro.

Celui-ci marque **la fin d'une chaîne de caractère** en délaissant complètement tout les caractères qui peuvent suivre (comme l'extension d'un fichier par exemple).

Pour exploiter cette vulnérabilité, il suffit d'utiliser burp et de modifier la requête de sorte à :

- Modifier le content-type (si une sécurité MIME est présente).
- Ajouter un null byte suivi par une extension de fichier autorisé.

Voici la <span style="text-decoration: underline;">requête initiale</span> lors de l'envoi du fichier **payload.php** :

[![image.png](https://wiki.neopipe.fr/uploads/images/gallery/2023-11/scaled-1680-/tzLimage.png)](https://wiki.neopipe.fr/uploads/images/gallery/2023-11/tzLimage.png)

Et voici la <span style="text-decoration: underline;">requête modifiée</span> :

[![image.png](https://wiki.neopipe.fr/uploads/images/gallery/2023-11/scaled-1680-/20timage.png)](https://wiki.neopipe.fr/uploads/images/gallery/2023-11/20timage.png)

Une fois la requête envoyée et le fichier correctement envoyé sur le serveur, il ne reste plus qu'à trouver le chemin du fichier **payload.php** (*et non payload.php%00.jpeg car la fonction basenaem() a retiré toute cette partie du nom du fichier*).