WordPress · 9 min · publié le 4 février 2025 · mis à jour le 16 juillet 2025

Des PHP dans wp-content/uploads : interdire l'exécution

Après avoir retiré les PHP de `wp-content/uploads`, un `.htaccess` (ou une règle Nginx) qui refuse l'exécution évite la récidive la plus simple. C'est le correctif que l'on pose le plus souvent — les médias restent, les scripts non.

Réponse directe

Après avoir retiré les fichiers, un .htaccess dans uploads qui refuse le PHP évite la récidive la plus simple. C'est le correctif que l'on pose le plus souvent.

php dans uploads uploads wordpress malware interdire php médias

Pourquoi il n'y a rien à exécuter ici

WordPress y stocke des images, PDF, parfois des MP3. Aucun besoin de PHP. Un `index.php` vide « pour lister » n'est pas requis ; un `index.php` de 12 Ko l'est encore moins. Tout PHP ici est suspect jusqu'à preuve du contraire (et la preuve est rare).

C'est la rampe après CF7 upload, un plugin vulnérable, un File Manager, un thème nulled. CF7, File Manager.

Cherchez `*.php`, `*.phtml`, `*.php.jpg`, `.php.` , et les « images » dont les premiers octets sont `<?php`. Les `.htaccess` locaux qui font `AddType` / `SetHandler` sur les jpg sont aussi importants que les fichiers : ils transforment une photo en script. Ne videz pas les dossiers d'années : vous tuez le site visuel. Retirez les scripts, posez l'interdiction d'exécution, testez qu'un `test.php` déposé temporairement ne s'exécute plus.

Un `index.php` vide de 0 octet pour empêcher le listing n'est pas requis si le serveur a déjà `Options -Indexes`. Un index.php de 12 Ko l'est. Les « caches » d'optimisation qui posent du PHP ici se documentent ou se sortent. Le Deny doit les casser ou les lister comme exceptions assumées — pas les ignorer.

Trouver .php, .phtml, .php.jpg

Recherche FTP / `find` : `*.php`, `*.phtml`, `*.phar`, `*.php5`, `*.php.jpg`, `*.jpg.php`, fichiers commençant par un point `.php`. Les dates hors publications de médias. Les noms `cache`, `temp`, `x`, `wp-tmp`.

Un `.png` dont les premiers octets sont `<?php` : ce n'est pas une image. Téléchargez, ouvrez. Les « miniatures » WordPress légitimes sont des vrais JPEG.

Les noms `cache`, `temp`, `x`, `wp-tmp`, les fichiers commençant par un point. Un `.png` de 12 Ko qui commence par `<?php` n'est pas une miniature WordPress (celles-ci sont de vrais JPEG). Téléchargez, ouvrez, ne vous fiez pas à l'extension.

  • Extensions PHP et doubles extensions.
  • Fichiers cachés (point en tête).
  • En-tête `<?php` dans un « média ».

Le .htaccess local qui force le contraire

Un `.htaccess` dans `uploads` ou un sous-dossier avec `AddType application/x-httpd-php .jpg` ou `SetHandler` : les images deviennent des scripts. Retirez ces règles. C'est aussi important que retirer le fichier.

Wordfence / iThemes peuvent écrire des règles. Relisez : gardez un Deny PHP, pas un AddHandler pirate.

Interdire l'exécution, pas vider le dossier

Apache : dans `uploads`, refuser le moteur PHP (`php_flag engine off` selon le setup, ou `Require all denied` sur `*.php`, ou `<FilesMatch>`). Testez qu'une URL `/wp-content/uploads/test.php` ne s'exécute plus (déposez un fichier temporaire puis retirez-le).

Ne videz pas les années `2020/` : vous tuez le site visuel. Retirez les scripts, gardez les médias. Supprimer malware.

Selon l'hébergeur : `php_flag engine off`, `FilesMatch` deny, ou une case « ne pas exécuter PHP dans uploads » chez o2switch / WP Cloud. Testez avec un fichier temporaire que vous retirez. Sans test, la règle est décorative.

Nginx, IIS, CDN

Nginx ignore le `.htaccess`. Règle `location ~* /wp-content/uploads/.*\.php` return 403. Chez o2switch / WP Cloud, un réglage « ne pas exécuter PHP dans uploads » existe parfois : cochez-le.

Un CDN qui sert le HTML/PHP depuis l'origine : le Deny doit être à l'origine. Un CDN « cache everything » peut resservir un vieux PHP ; purge.

Double extension et « image » qui commence par php

Apache négocie parfois `.php.jpg` comme PHP. D'où l'interdiction large, pas seulement `*.php`. Les MIME envoyés par le navigateur à l'upload mentent ; le serveur doit filtrer l'extension réelle.

Formulaires et File Manager

Coupez les uploads de formulaires inutiles. Désinstallez File Manager après usage. Sinon le `.htaccess` sera contourné par un admin qui dépose à la racine. La règle uploads n'est pas un pare-feu global.

Coupez les uploads de formulaires inutiles. Désinstallez File Manager après usage. Sinon quelqu'un dépose à la racine et votre .htaccess uploads ne sert à rien. File Manager.

Contrôle à J+7

Recherche PHP à nouveau. Dates. Un mu-plugin peut réécrire un PHP dans uploads. Backdoor.

Guide WP, créer un espace.

Nginx ignore le `.htaccess` : règle `location` dédiée. Un CDN cache everything ressert un vieux PHP : purge. La règle uploads n'empêche pas un File Manager de déposer à la racine. Contrôle à J+7 : un mu-plugin peut réécrire un PHP ici. Backdoor PHP. Créer un espace.

J+7 sans nouveau PHP + probe toujours 403 : la règle tient. Un nouveau `.php.jpg` : mu-plugin ou formulaire encore ouvert. CF7, File Manager.

Plugins qui écrivent du PHP ici, et les PDF

Quelques caches / builders posent du PHP dans uploads : mauvaise pratique. Sortez-les du web ou changez de plugin. En attendant, documentez-les : un Deny trop large les cassera, un Deny trop étroit laissera le `.php.jpg`. Les PDF peuvent être dangereux pour le poste qui les ouvre ; pour le serveur, l'urgence reste l'exécution PHP.

Ne bloquez pas tout `wp-content` en PHP : thèmes et plugins en ont besoin. `uploads`, `upgrade`, dossiers backup. Multisite : chaque `sites/ID`. Multisite.

Wordfence qui « répare » un jpg : vérifiez que ce n'était pas une photo. Comparez au backup. Créer un espace.

Tester que la règle tient vraiment

Déposez `uploads/__probe.php` qui fait `<?php echo 'PROBE';`, appelez l'URL : vous devez voir le source ou un 403, pas PROBE. Effacez le probe. Refaites après une MAJ Wordfence / Solid qui réécrit les .htaccess. Chez Nginx, le .htaccess n'a jamais existé : la location doit être dans le vhost.

J+7 : find des PHP à nouveau. Un mu-plugin réécrit. Backdoor PHP. Créer un espace.

Le probe est le seul PHP que vous posez volontairement ici, et il ne reste pas cinq minutes.

Questions fréquentes

Un plugin légitime met du PHP dans uploads ?

+
C'est une mauvaise pratique. Cachez-le hors web ou changez de plugin. En attendant, ces PHP restent une cible. Documentez-les si vous les gardez. C'est une mauvaise pratique. Documentez-les si vous les gardez, ou sortez-les du web.

Je bloque tout wp-content en PHP ?

+
Les plugins et le thème ont besoin de PHP. `uploads` seulement, plus éventuellement `upgrade` / `backup` dossiers. Les plugins et le thème ont besoin de PHP. uploads seulement, plus les dossiers backup.

Les PDF peuvent être des malware ?

+
Pour le poste qui les ouvre, parfois. Pour le serveur WordPress, l'urgence c'est l'exécution PHP. Ne servez pas de PDF d'un inconnu en confiance. Pour le poste client parfois. Pour le serveur, l'urgence est l'exécution PHP.

Multisite : uploads par site ?

+
`blogs.dir` ou `uploads/sites/ID/`. Même règle sur chaque arborescence. Multisite. Même règle sur uploads/sites/ID et blogs.dir.

Wordfence a « réparé » un jpg ?

+
Vérifiez que ce n'était pas une vraie photo corrompue par un faux positif. Les médias, on compare au backup, on ne repair pas à l'aveugle. Vérifiez que ce n'était pas une vraie photo. Les médias, on compare au backup.
À lire ensuite
File Manager Contact Form 7 Supprimer un malware WP Backdoor PHP WordPress piraté Déclarer mon site