Cybreach Consulting Prendre RDV
Retour aux articles
Vulnérabilités

Téléversement de fichiers arbitraires : validation insuffisante et exécution de code

L'upload de fichier devient une vulnérabilité critique quand l'application permet de téléverser des fichiers exécutables dans un répertoire accessible par le serveur web. Un attaquant peut téléverser un webshell (fichier PHP, JSP, ASPX contenant du code malveillant), y accéder via une URL, et exécuter des commandes sur le serveur. C'est une des voies d'exploitation les plus directes vers une compromission complète.

Webshell PHP minimal

<?php system($_GET['cmd']); ?>

# Accès : https://app.example.com/uploads/shell.php?cmd=id
# Résultat : uid=33(www-data) gid=33(www-data)

Contournement des validations côté client

La validation du type de fichier côté client (attribut accept du formulaire HTML, vérification JavaScript du MIME type) est contournable en quelques secondes. Un attaquant intercepte la requête HTTP après que le navigateur l'a construite (avec Burp Suite ou un proxy) et modifie l'extension du fichier ou le Content-Type avant envoi. Ces validations peuvent améliorer l'expérience utilisateur mais n'ont aucune valeur sécurité.

Validations côté serveur nécessaires

Toutes les validations doivent être effectuées côté serveur. Les vérifications à effectuer : extension de fichier (liste blanche d'extensions autorisées, pas une liste noire), type MIME réel (lire les magic bytes du fichier, pas se fier au Content-Type de la requête), taille maximale, nom de fichier (générer un nom aléatoire, ne jamais utiliser le nom fourni par l'utilisateur), contenu (scanner les fichiers image avec une bibliothèque dédiée pour détecter du code caché).

Validation d'upload sécurisée (Node.js)

const path = require('path');
const crypto = require('crypto');
const FileType = require('file-type');

async function handleUpload(file) {
  // 1. Vérification par magic bytes (pas par extension ou Content-Type)
  const type = await FileType.fromBuffer(file.buffer);
  const ALLOWED = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
  if (!type || !ALLOWED.includes(type.mime)) {
    throw new Error('Type de fichier non autorisé');
  }

  // 2. Nom de fichier aléatoire avec extension validée
  const ext = type.ext;
  const safeName = crypto.randomBytes(16).toString('hex') + '.' + ext;

  // 3. Stockage hors du répertoire web (non exécutable)
  const dest = path.join('/var/uploads', safeName);
  await fs.writeFile(dest, file.buffer);

  return safeName;
}

Isolation des fichiers uploadés

Même avec une validation correcte, les fichiers uploadés ne doivent jamais être stockés dans un répertoire accessible directement par le serveur web. Les stocker hors du document root (un répertoire que le serveur web ne sert pas directement) et les servir via un endpoint dédié qui contrôle les accès. Cette architecture garantit que même si un fichier malveillant passe la validation, il ne peut pas être exécuté.

Pour les applications qui acceptent des images, envisager de les retraiter (redimensionner, re-encoder) avec une bibliothèque image avant de les stocker. Cette opération détruit la plupart des charges malveillantes éventuellement cachées dans les métadonnées ou les pixels.

Une question après la lecture ?

Votre application accepte des fichiers uploadés ? Envoyez un message.

Ou réservez directement un cadrage de 30 minutes

Réserver un appel