vendredi 25 septembre 2026

À propos

Contact

Sécurité

Upload de fichiers dans une extension : valider le type et le contenu

Un champ d'envoi de fichier mal validé dans une extension maison ouvre la porte à l'exécution de code. La bonne méthode, étape par étape.

Par Clément Hadrot • 24 novembre 2020 • 4 min de lecture • Aucun commentaire
Upload de fichiers dans une extension : valider le type et le contenu

Un client demande un formulaire permettant à ses utilisateurs d’envoyer un justificatif, une photo de profil ou un document PDF. La demande semble anodine, mais un champ d’upload mal sécurisé dans une extension maison figure parmi les vecteurs de compromission les plus fréquents que nous rencontrons en audit, souvent bien plus dangereux qu’une simple faille XSS.

Le problème ne vient presque jamais de l’absence totale de vérification — la plupart des développeurs pensent au moins à contrôler l’extension du fichier. Il vient de vérifications incomplètes qui donnent une fausse impression de sécurité. Voici la démarche complète, étape par étape, pour traiter un upload correctement dans une extension WordPress.

Étape 1 : ne jamais faire confiance à l’extension déclarée seule

Un fichier nommé photo.jpg peut très bien contenir du code PHP : rien n’empêche un attaquant de renommer un script malveillant avant de l’envoyer. Vérifier uniquement l’extension du nom de fichier, via une simple comparaison de chaîne, ne protège donc de rien face à un attaquant un minimum informé.

WordPress fournit une fonction native conçue précisément pour ce cas : wp_check_filetype_and_ext(). Elle croise l’extension déclarée avec le type MIME réellement détecté à partir du contenu du fichier, et rejette toute incohérence.

$verification = wp_check_filetype_and_ext(
    $_FILES['justificatif']['tmp_name'],
    $_FILES['justificatif']['name']
);

if ( empty( $verification['ext'] ) || empty( $verification['type'] ) ) {
    wp_die( __( 'Type de fichier non autorisé.', 'mon-extension' ) );
}

Étape 2 : restreindre à une liste blanche stricte de types MIME

Même correctement détecté, un type MIME ne doit être accepté que s’il figure explicitement dans la liste des formats attendus pour ce formulaire précis. Accepter « tout ce qui est une image » est déjà trop large si seul le JPEG est réellement utile :

$types_autorises = array(
    'jpg|jpeg' => 'image/jpeg',
    'png'      => 'image/png',
    'pdf'      => 'application/pdf',
);

$verification = wp_check_filetype_and_ext(
    $_FILES['justificatif']['tmp_name'],
    $_FILES['justificatif']['name'],
    $types_autorises
);
L'essentiel à retenir : L'extension MIME ne suffit jamais à garantir le vrai type d'un fichier ; wp_check_filetype_and_ext croise extension et contenu réel ; Stocker hors de webroot élimine le risque même en cas d'erreur

Étape 3 : passer par wp_handle_upload plutôt que réinventer le stockage

Une fois le fichier validé, la fonction wp_handle_upload() gère le déplacement vers un emplacement final, génère un nom de fichier sûr et évite les collisions. Elle attend un tableau de type $_FILES et un jeu d’options :

require_once ABSPATH . 'wp-admin/includes/file.php';

$resultat = wp_handle_upload(
    $_FILES['justificatif'],
    array( 'test_form' => false, 'mimes' => $types_autorises )
);

if ( isset( $resultat['error'] ) ) {
    wp_die( esc_html( $resultat['error'] ) );
}

Réécrire soi-même la logique de déplacement de fichier avec move_uploaded_file() brut est possible, mais chaque détail oublié (nom de fichier non assaini, absence de vérification d’erreur d’upload) réintroduit un risque que wp_handle_upload() gère déjà.

Étape 4 : stocker les fichiers sensibles hors de portée directe

Pour des documents qui ne doivent pas être accessibles publiquement par simple connaissance de l’URL (justificatifs d’identité, factures), le dossier wp-content/uploads standard n’est pas adapté : tout fichier qui y est déposé devient accessible à quiconque devine ou trouve son chemin.

  • Stocker ces fichiers dans un répertoire dédié, en dehors du chemin racine servi par le serveur web.
  • Servir leur contenu via un script PHP qui vérifie les droits de l’utilisateur avant de le transmettre (avec un en-tête Content-Disposition adapté).
  • Combiner cette approche avec la règle qui interdit l’exécution de PHP dans le dossier d’upload, en défense supplémentaire.

Ce qu’il ne faut jamais faire

Un formulaire d’upload qui fait confiance à l’extension du nom de fichier fourni par le navigateur, c’est comme vérifier l’identité de quelqu’un en lui demandant simplement de se présenter.

Se fier au type MIME envoyé par le navigateur dans $_FILES['champ']['type'] relève de la même erreur : cette valeur est entièrement contrôlée par le client et se falsifie sans effort. Seule la détection basée sur le contenu réel du fichier, via wp_check_filetype_and_ext(), mérite d’être considérée comme fiable côté serveur.

En résumé

Sécuriser un upload dans une extension WordPress tient en quatre réflexes : vérifier le contenu réel du fichier et pas seulement son nom, restreindre à une liste blanche de types précis, s’appuyer sur wp_handle_upload() plutôt que réinventer la logique de stockage, et isoler les documents sensibles hors de portée directe. Chacune de ces étapes ferme une porte que les attaquants automatisés testent en premier.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi