Interdire l'exécution PHP dans les dossiers d'upload
Le correctif le moins coûteux après un incident : que rien ne s'exécute dans les dossiers de médias. .htaccess ou équivalent Nginx. Vérifiez qu'aucun plugin légitime n'a besoin d'y lancer du PHP — c'est rare, et discutable.
Le correctif le moins coûteux après un incident. .htaccess ou config Nginx. Vérifiez qu'aucun plugin légitime n'a besoin d'y exécuter du PHP — c'est rare et discutable.
Pourquoi les uploads sont la cible
C'est le dossier que le métier *doit* laisser inscriptible. Formulaire, médiathèque, import CSV. L'attaquant y dépose un PHP (ou un faux média que le handler exécute). Le cœur CMS, lui, est plus souvent en lecture. D'où la fréquence des shells dans `uploads`, `media`, `img`, `files`.
Un listing de répertoire ouvert aide à les trouver. Fermez l'indexation en même temps. Ce n'est pas le même geste, ça se complète.
La backdoor n'*habite* pas que là. Le filet là réduit la pose *facile*. Il ne remplace pas la chasse à la racine et aux mu-plugins.
Ce que « interdire » veut dire
Le serveur ne *traite* plus ces fichiers comme du PHP. Ils peuvent encore être *téléchargés* s'ils sont publics (un `.php` servi en texte est moins grave qu'exécuté, mais sortez-le quand même). L'objectif incident : plus d'exécution.
On ne publie pas ici un copier-coller universel : les directives varient, un mauvais bloc casse les images ou tout le vhost. On pose le principe, on s'appuie sur la doc de l'hébergeur / du CMS, on teste.
Windows / IIS : restriction d'exécution sur le dossier médias, même intention.
- Pas d'exécution dans les médias.
- Pas de listing de dossier.
- Les vrais PHP métier restent ailleurs.
Apache : un filet, pas une porte
Un `.htaccess` *votre*, documenté, dans `uploads` (et équivalents), qui refuse le moteur PHP et les handlers pirates. Distinguez-le d'une ligne déjà là posée par l'attaquant. Copiez l'existant, puis posez le filet propre. Voir l'article htaccess pour ne pas tout vider.
Si `AllowOverride` ignore le fichier, le filet est mort. Ticket host : « comment désactiver PHP dans ce dossier ? » Ils ont parfois une case panel. Mieux qu'un forum.
Un filet à la racine qui casse WordPress n'est pas le but. *Dossier médias seulement*.
Nginx et les hébergeurs figés
La règle vit dans le vhost (`location` sur le chemin médias). En mutualisé, vous n'y avez pas accès : panel, ticket, ou un fichier `.user.ini` / politique PHP selon l'offre. Ne déposez pas un `.htaccess` en croyant que Nginx le lira — sauf si on vous l'a dit.
Plesk / ISPconfig ont souvent une UI « PHP pour ce dossier : aucun ». C'est le bon bouton. Notez-le dans le registre (mesure datée).
CDN qui exécute au bord : rare pour du PHP, possible pour du JS. Autre couche, inventaire pixels.
Plugins qui « ont besoin » de PHP là
Quelques constructeurs, caches, ou vieux modules « image processor » exécutent un PHP dans un sous-dossier de médias. C'est rare et discutable : ça mélange données et code. Après un incident, on refuse par défaut. Si un plugin casse, on cherche une version qui écrit *hors* web ou dans un dossier dédié *non* uploads, ou on change d'outil.
Ne rouvrez pas tout `wp-content` en exécution « le temps que ça marche ». C'est le chemin du 777. Permissions.
Un prestataire qui exige PHP dans uploads pour un thème nulled : changez de thème, pas de filet.
Vérifier que c'est effectif
Avec l'hébergeur ou un prestataire : un fichier test *temporaire* que *vous* contrôlez, puis retrait immédiat. Le critère : le moteur ne l'exécute pas. Vous n'utilisez pas un shell trouvé. Vous ne laissez pas le test en ligne.
Les médias légitimes (jpg, pdf) doivent encore s'afficher. Si tout est 403, le bloc est trop large. On ajuste, on ne jette pas le filet.
Documentez « testé le …, retiré le fichier de test ». Preuve pour vous, pas un exploit.
Limites du filet
N'empêche pas l'exécution à la racine, dans un thème, un mu-plugin, un cron. N'empêche pas une injection SQL. N'empêche pas un compte admin. Filet, pas château.
Un handler *au-dessus* (vhost) peut contourner votre htaccess. D'où la vérif réelle, pas seulement le fichier posé.
Les doubles extensions et les fichiers sans extension : le filet bien fait les couvre ; un filet « seulement .php » non. Faites relire la règle.
Dans quelle séquence le poser
Après copie, après rotation panel, pendant ou juste après la chasse aux fichiers — pas comme *seul* geste le vendredi soir. Avant de crier victoire et de faire le warmup mail ou le réexamen Google.
Les 48 h : si un PHP *revient* dans uploads et *s'exécute encore*, le filet n'est pas actif. Si un PHP revient et *ne s'exécute plus*, il reste une écriture (porte ailleurs) mais la casse est moindre. Deux diagnostics.
Créer un espace si le panel n'offre rien et que Nginx vous est fermé. Joignez « on veut no-exec sur /uploads ». C'est un objet clair.
- Médias : pas d'exécution, pas d'index.
- Vérifier pour de vrai, retirer le test.
- Le reste de la carte portes ensuite / autour.