Sécurité WordPress : prévenir l’upload de fichiers exécutables
Sur un site WordPress, la zone d’upload ressemble à un détail. Pourtant, c’est souvent l’endroit le plus exposé, parce qu’il colle directement à une fonctionnalité “normale” de WordPress: ajouter une image, un PDF, un fichier média. Le problème, c’est que des attaquants essayent justement de détourner cette porte d’entrée. Leur objectif est simple: parvenir à déposer un fichier sur le serveur, puis le faire exécuter (directement ou indirectement) ou déclencher un comportement dangereux.
La bonne approche consiste rarement à “tout bloquer”. Elle consiste plutôt à réduire la surface d’attaque, à rendre l’exécution impossible dans les dossiers d’uploads, à filtrer strictement ce qui peut entrer, et à surveiller ce qui se passe. C’est là que la sécurisation WordPress devient concrète, pas théorique.
Le vrai risque: quand un upload devient une exécution
Un fichier “exécutable” n’est pas forcément un binaire. Sur une configuration classique, l’exécution vient presque toujours d’un interpréteur côté serveur: PHP, parfois aussi d’autres technologies selon les configurations (ou selon certains cas limites).
Dans WordPress, un attaquant peut tenter plusieurs scénarios:
Upload d’un fichier PHP déguisé (extension .php ou variantes comme .phtml), parfois avec double extension. Upload d’un fichier HTML ou SVG “actif”, conçu pour déclencher du code côté navigateur ou pour contourner des protections. Upload de macros ou contenus malveillants qui ne s’exécutent pas sur le serveur, mais qui menacent l’utilisateur au téléchargement (PDF piégés, Office avec macros). Upload de polyglots, c’est à dire des fichiers qui ont l’air d’un format valide à l’œil ou selon des vérifications simples, tout en contenant un contenu exploitable.
Ce qui rend le problème délicat, c’est que “bloquer par extension” est rarement suffisant. Une extension peut être trompée, et certains contrôles côté WordPress ou côté plugin reposent sur des règles partielles. Votre première ligne de défense doit donc être l’impossibilité d’exécution dans le répertoire uploads.
Commencer par la vérité du serveur: où s’exécute réellement le code
Avant de durcir quoi que ce soit, il faut comprendre une chose: WordPress n’est pas le seul acteur. Le comportement d’exécution dépend d’abord du serveur web et de sa configuration.
Dans beaucoup d’installations, les uploads sont servis comme des fichiers statiques, mais “statique” ne veut pas dire “non interprétable”. Si, par erreur, votre serveur est configuré pour interpréter le PHP dans certains dossiers, alors un simple dépôt d’un fichier .php peut suffire.
Deux questions pragmatiques à vous poser:
Est-ce que le dossier wp-content/uploads peut exécuter du code côté serveur (PHP ou autre) si un fichier de type correspondant y est placé ? Est-ce que vous avez des répertoires supplémentaires, comme wp-content/plugins, wp-content/themes ou des endpoints qui peuvent rejouer un fichier de manière active ?
Si vous n’avez pas l’habitude de tester, vous pouvez le faire avec prudence, en conditions contrôlées (en staging, sur une copie du site). L’objectif n’est pas “d’exploiter”, mais de vérifier la politique d’exécution.
Rendre l’exécution impossible dans wp-content/uploads
C’est la mesure la plus structurante. L’idée: même si un fichier exécutable arrive au mauvais endroit, il ne doit jamais être interprété. Sur Apache, cela passe souvent par des règles dans .htaccess. Sur Nginx, cela passe plutôt par une configuration dans le bloc server.
Sur Apache, une règle classique consiste à empêcher l’exécution PHP dans les dossiers d’uploads, en forçant tout ce qui ressemble à du PHP à être traité comme du texte, ou à interdire l’interprétation.
Sur Nginx, le principe est similaire: désactiver les scripts dans ces emplacements, ou garantir que le PHP n’est géré que par un chemin explicitement prévu, comme index.php pour WordPress.
Le point important: n’appliquez pas un durcissement “au hasard”. Le bon réglage dépend du mode d’exécution PHP (mod_php, php-fpm, FastCGI), et de la manière dont vous gérez WordPress aujourd’hui. Si vous avez la moindre incertitude, c’est un bon cas d’échange avec votre hébergeur. Sur une pile mal comprise, vous pouvez casser des fonctionnalités légitimes (par exemple des scripts d’images, des fichiers utilisés par un plugin de conversion, ou certains flux).
Filtrer à la source côté WordPress, sans se mentir
Une fois l’exécution bloquée côté serveur, vous pouvez renforcer la sélection des fichiers acceptés au niveau WordPress. Cela ne remplace pas la protection serveur, mais ça réduit fortement les chances qu’un fichier dangereux arrive jusque sur le disque.
WordPress gère déjà l’upload avec une validation d’extension et une vérification de type basée sur le fichier. Le piège, c’est que selon les versions, les configurations, et surtout les plugins, la validation peut varier. Certains plugins étendent les formats autorisés, parfois “trop” généreusement.
Votre stratégie la plus fiable consiste à raisonner en allowlist (liste blanche) plutôt qu’en blocklist. En prose: n’autorisez que les formats utiles pour votre site, et évitez les formats “permissifs” ou difficiles à analyser.
Dans la pratique, beaucoup de sites se contentent de fichiers images, plus éventuellement PDF et quelques documents. Laisser passer des formats comme SVG, HTML ou des archives lourdes augmente la complexité de sécurité.
Le cas des images, et le piège du SVG
Les images sont généralement acceptées sans douleur, jusqu’au jour où quelqu’un vous envoie un SVG “mal formé” ou contenant des charges utiles. Un SVG n’est pas un simple bitmap. C’est du XML, et selon la manière dont il est servi puis interprété par le navigateur, il peut devenir un vecteur d’attaque (XSS ou comportement inattendu).
Si votre site a vraiment besoin de SVG (icônes, schémas), vous devrez appliquer une validation stricte, ou une politique d’export qui neutralise le contenu actif. Sinon, le plus simple reste de désactiver l’upload de SVG ou de le traiter comme un format à risque.
Double extension, noms trompeurs, et variantes
On voit souvent des noms du type photo.jpg.php ou document.pdf.php. Si votre filtrage ne regarde que l’extension “la première vue”, ça passe. S’il regarde uniquement le type MIME “déclaré” côté client, ça passe aussi.
La robustesse vient d’un contrôle cohérent sur:
l’extension finale réellement utilisée par WordPress (pas un suffixe en apparence), le type MIME détecté, et si possible, un contrôle du contenu (par exemple une inspection des en-têtes pour les formats attendus).
WordPress n’offre pas https://gardewp.fr/securite-wordpress/ à lui seul un scanner antivirus. Mais vous pouvez imposer des règles plus strictes et réduire les angles morts.
Le rôle des plugins de sécurité: utile, mais à vérifier
Les plugins de sécurisation WordPress apportent souvent des modules “file upload” et des filtrages. Leur valeur est réelle, parce qu’ils encapsulent des bonnes pratiques, parfois avec des mises à jour.
Mais il y a un revers: un plugin peut être configuré “trop large” pour conserver la compatibilité. Ou alors, il peut se baser sur des heuristiques qui ne couvrent pas tous vos cas d’usage (comme un format autorisé “pour un autre site” mais rarement utilisé ici).
Ce que je fais en mission, c’est auditer la configuration de ces modules en trois points:
Est-ce que l’allowlist correspond à vos formats réellement nécessaires ? Est-ce que le plugin bloque au moment de l’upload, avant d’écrire sur le disque, ou seulement après ? Est-ce qu’il logue suffisamment pour vous donner une piste (nom, type, user, date, IP) en cas de tentative ?
Sans logs actionnables, vous n’êtes pas en sécurité, vous êtes juste “confiant”.
Permissions et chemins: réduire ce que l’attaquant peut faire une fois le fichier posé
Même en bloquant l’exécution, un attaquant peut viser d’autres objectifs: remplir l’espace disque, déposer des fichiers volumineux, ou exploiter des chemins d’accès annexes.
Deux leviers “de fond” valent souvent plus que des réglages fins:

Restreindre les permissions sur les répertoires sensibles, de sorte que le système ne soit pas en mode trop ouvert. Éviter que des répertoires où PHP pourrait être interprété soient accessibles de manière interprétable depuis les uploads.
Concrètement, si votre configuration permet au web server d’écrire dans des zones inattendues, c’est une faille de conception, pas un détail. Sur un hébergement bien tenu, les uploads ont des permissions adaptées pour stocker des médias, pas pour devenir une plateforme d’exécution.
Surveiller les tentatives: l’oubli le plus fréquent
Bloquer l’upload est indispensable, mais le vrai confort vient quand vous savez ce qui se passe. Un attaquant qui teste un site commence souvent par des tentatives répétées, parfois sur des chemins connus.
Si vous avez:
une alerte sur les erreurs 4xx liées à des uploads refusés, des logs serveur qui mentionnent la tentative d’un fichier rejeté, et des traces applicatives côté WordPress,
Alors vous pouvez détecter un pattern. Et un pattern, c’est ce qui vous aide à distinguer une mauvaise configuration isolée d’une campagne active.
Dans beaucoup de cas, vous verrez rapidement que les tentatives viennent d’un profil ou d’une plage d’IP, et que le type de fichier rejeté est toujours le même (par exemple des variantes PHP avec des extensions déguisées). Cette information vous permet d’ajuster précisément les règles, au lieu de “durcir partout” et casser des usages.
Une configuration robuste en pratique: politique de formats et blocage serveur
Voici comment j’aborderais une sécurisation WordPress orientée “uploads exécutables”. L’objectif est de créer une barrière en couches, pas un pari.
Côté serveur, empêcher l’interprétation PHP (et autres scripts) dans wp-content/uploads et autres répertoires de médias. Côté WordPress, n’autoriser que des formats nécessaires, et refuser ceux qui sont difficiles à neutraliser (exemples: SVG non traité, HTML). Traiter les cas particuliers, comme double extension et noms trompeurs, en exigeant une validation cohérente. S’assurer que les plugins de sécurité ne se contentent pas de “taguer” la demande, mais qu’ils empêchent vraiment l’écriture ou l’enregistrement final du fichier dangereux. Vérifier et centraliser les logs pour repérer les tentatives et détecter un glissement de configuration.
Vous pouvez le mettre en œuvre étape par étape sans tout casser, surtout si vous faites une séance de test sur une copie de staging.

Petite checklist de vérification (avant de déployer)
Déclenchez un upload de fichier “test” contenant une extension trompeuse, et vérifiez qu’il est rejeté. Testez le comportement dans wp-content/uploads sur le serveur de déploiement, pas seulement dans WordPress. Contrôlez que les formats autorisés correspondent à votre besoin réel (pas à un historique vague). Vérifiez que les logs indiquent qui a tenté quoi, et quand. Faites un test sur une longue série de noms de fichiers “à la main” (espaces, ponctuation, double extensions).
Edge cases qui reviennent: pourquoi les règles doivent être nuancées
La sécurité sur WordPress se heurte rarement à une absence de mesures. Elle se heurte à l’équilibre. Un filtrage trop strict peut casser des workflows légitimes, par exemple:
un plugin de traduction qui charge des fichiers de contenu spécifiques, une bibliothèque qui importe des médias avec des formats rares, un constructeur de formulaires qui attend un modèle ou un document dans un format donné.
À l’inverse, un filtrage trop souple vous laisse une échappatoire.
Les archives: zip, tar, et compagnie
Les archives sont pratiques pour l’import, mais elles augmentent le risque. Un fichier archive peut contenir des choses inattendues, y compris des fichiers exécutables. Si vous acceptez des archives, vous devez aussi contrôler ce qu’il se passe ensuite: décompression automatique, stockage temporaire, exécution par un processus tiers.
Souvent, le mieux est de refuser les archives au niveau WordPress, ou de réserver leur acceptation à un endpoint contrôlé, avec un processus dédié.
Les fichiers “log” et “config” qui traînent
Un upload qui accepte n’importe quelle extension peut mener à des dépôts de fichiers “non destinés à être servis”. Même si le serveur ne les exécute pas, ils peuvent être récupérés à distance, exposant des informations sensibles si le contenu est exploitable, ou aidant un attaquant à cartographier votre environnement.
Si vos uploads sont strictement dédiés aux médias, vous devez aligner la politique d’uploads à cette réalité. La moindre “exception” doit être justifiée.
Durcir sans casser: choisir vos compromis
Le bon compromis dépend de votre site.
Si vous avez un site éditorial, l’allowlist peut être courte: images, éventuellement PDF. Si vous gérez une plateforme avec beaucoup de contenus téléversés par des utilisateurs, vous aurez besoin d’un contrôle plus fort, et probablement d’un workflow de quarantaine ou de validation. Si vous êtes en multi-auteurs, la probabilité d’erreur humaine augmente, et c’est encore plus important d’avoir une validation cohérente et des permissions strictes.
Un détail que je rencontre souvent: des sites qui ont commencé avec une règle d’upload “raisonnable”, puis qui ont progressivement ajouté des formats pour satisfaire des demandes. Sans nettoyage, vous finissez avec une liste blanche trop large pour la réalité actuelle.
Un audit de formats est un travail simple, mais souvent oublié. Il suffit de regarder ce que les médias contiennent réellement sur plusieurs mois. Si un format autorisé n’apparaît presque jamais, c’est un candidat naturel à la suppression.
Procédure de test sécurisée en staging
Si vous voulez éviter les surprises, le staging est votre ami. Je conseille un test qui ne se limite pas au “ça marche”. Il faut tester le refus, parce que c’est là que les mauvaises configurations se révèlent.
Faites un test d’upload de fichiers avec des extensions trompeuses, et vérifiez aussi:
le comportement du serveur quand un fichier est tenté, la réponse HTTP (succès, erreur, redirection), et le fait que le fichier n’apparaît pas dans la médiathèque.
Le but n’est pas d’optimiser la charge utile. Le but est de vérifier que votre configuration ne laisse pas un chemin facile.
Réflexe final: ne confondez pas “refus WordPress” et “sécurité réelle”
WordPress peut refuser un upload, et un plugin peut afficher “fichier non autorisé”. C’est bien. Mais si l’exécution reste possible au niveau serveur, vous avez un risque structurel. L’inverse est aussi vrai: bloquer côté serveur, sans filtrer à la source, peut vous exposer à des tentatives répétées qui remplissent l’espace, créent du bruit, et augmentent la probabilité de conditions imprévues.
La bonne approche, c’est la combinaison: interdiction d’exécution dans les dossiers d’uploads, filtrage côté WordPress, politique de formats claire, et surveillance.
C’est une sécurisation WordPress qui s’inscrit dans la durée: au lieu de courir après chaque nouvelle méthode d’attaque, vous construisez une barrière qui rend les “trucs exécutables” inutiles, même s’ils arrivent jusqu’à vous.
Si vous voulez, dites-moi votre contexte (hébergeur, Apache ou Nginx, PHP-FPM ou autre, types de fichiers réellement nécessaires). Je peux vous proposer une politique d’allowlist réaliste et les points à vérifier côté serveur, sans casser les usages légitimes.