Permettre à un utilisateur d’envoyer un fichier sur un serveur est une fonctionnalité puissante, mais elle ouvre une porte critique aux cyberattaques. Sans précautions strictes, un utilisateur malveillant pourrait uploader un script PHP (un « web shell ») et prendre le contrôle total de votre serveur.
Comprendre le fonctionnement des uploads en PHP
Lorsqu’un fichier est envoyé via un formulaire, PHP le place temporairement dans un dossier temporaire du serveur. Les informations relatives à ce fichier sont stockées dans la superglobale $_FILES. Cette variable contient le nom du fichier, son type, sa taille, son nom temporaire et le code d’erreur associé.
Ne faites jamais confiance aux données envoyées par le client, notamment le nom du fichier ou le type MIME déclaré par le navigateur, car ils peuvent être facilement falsifiés.
Étape 1 : Créer le formulaire HTML
Pour envoyer des fichiers, le formulaire doit impérativement contenir :
- La méthode
POST - L’attribut
enctype="multipart/form-data"
Sans cet attribut, le tableau $_FILES sera vide lors de la soumission du form.
<form action="upload.php" method="POST" enctype="multipart/form-data">
<label for="doc">Choisir un document (PDF, JPG, PNG) :</label>
<input type="file" name="doc" id="doc">
<button type="submit">Envoyer</button>
</form>Étape 2 : Valider la réception et la taille
Apres avoir creer le fichier upload.php, la première étape consiste à vérifier que le fichier a été transmis sans erreur et qu’il ne dépasse pas une taille maximale définie pour éviter les attaques par déni de service (DoS).
<?php
// Taille maximale : 2 Mo
$maxSize = 2 * 1024 * 1024;
if (!isset($_FILES['doc']) || $_FILES['doc']['error'] !== UPLOAD_ERR_OK) {
die("Erreur lors du téléchargement du fichier.");
}
if ($_FILES['doc']['size'] > $maxSize) {
die("Le fichier est trop volumineux (max 2 Mo).");
}
?>Étape 3 : Sécuriser le type de fichier
Vérifier l’extension du fichier (ex: .jpg,.jpeg,.svg,png,...) ne suffit pas, car un attaquant peut renommer shell.php en shell.jpg. Il faut analyser le contenu réel du fichier via son type MIME en utilisant l’extension finfo de PHP.
finfo vous retournera un tableau d’objet.
<?php
$allowedMimes = ['image/jpeg', 'image/png', 'application/pdf'];
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($_FILES['doc']['tmp_name']);
if (!in_array($mimeType, $allowedMimes)) {
die("Type de fichier non autorisé. Seuls les images et PDF sont acceptés.");
}
?>Étape 4 : Stockage sécurisé et renommage
Stocker un fichier avec son nom d’origine est dangereux (risques d’écrasement de fichiers système ou d’exécution de scripts via des caractères spéciaux). La meilleure pratique consiste à générer un nom unique et aléatoire avec uniqid()( qui va generer une chaine aléatoire)
A la fin du script vous trouverez le fichier dans le dossier upload.
<?php
// Dossier de destination (doit être hors de la racine web si possible)
$uploadDir = 'uploads/';
// Extraction de l'extension réelle basée sur le type MIME
$extensions = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'application/pdf' => 'pdf'];
$extension = $extensions[$mimeType];
// Génération d'un nom unique
$fileName = uniqid('file_', true) . '.' . $extension;
$destination = $uploadDir . $fileName;
if (move_uploaded_file($_FILES['doc']['tmp_name'], $destination)) {
echo "Fichier uploadé avec succès : " . htmlspecialchars($fileName);
} else {
echo "Une erreur est survenue lors du déplacement du fichier.";
}
?>Synthèse des mesures de sécurité
| Risque | Solution technique | Impact |
|---|---|---|
| Exécution de code | Vérification du type MIME via finfo | ✅ Critique |
| Surcharge serveur | Limitation de $_FILES['doc']['size'] | ✅ Important |
| Écrasement de fichiers | Renommage via uniqid() | ✅ Important |
| Accès direct aux fichiers | Stockage hors racine web ou .htaccess | ✅ Recommandé |
Conclusion
La gestion des uploads de fichiers sécurisés en PHP repose sur un principe simple : ne jamais faire confiance à l’entrée utilisateur. En combinant la vérification du type MIME, la limitation de la taille et le renommage systématique des fichiers, vous réduisez drastiquement la surface d’attaque de votre application. Pour une sécurité maximale, envisagez de stocker vos fichiers sur un service de stockage externe comme AWS S3 ou Google Cloud Storage.

