# Bloquer l’exécution de PHP dans wp-content/uploads sous nginx et Apache

> Le dossier des médias accepte des fichiers d'inconnus. Interdire à PHP de s'y exécuter neutralise la quasi-totalité des webshells déposés.

- Auteur : Clément Hadrot
- Publié le : 2020-09-28
- Mis à jour le : 2020-09-28
- Catégorie : Sécurité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/securite/bloquer-php-uploads-nginx-apache/

## L’essentiel

- uploads reçoit des fichiers d'origine externe, jamais du code de confiance
- Une règle serveur suffit à neutraliser un script PHP déposé
- Vérifiable en une requête avec un fichier test inoffensif

Le dossier `wp-content/uploads` a une particularité que beaucoup de propriétaires de sites oublient : c'est le seul endroit du serveur où des fichiers arrivent en continu depuis l'extérieur, via les formulaires de médiathèque, les extensions d'import ou parfois des formulaires de contact mal sécurisés. Si un attaquant parvient, par une faille quelconque, à y déposer un fichier `.php`, et que le serveur accepte de l'exécuter, la partie est perdue : il dispose d'un accès direct à l'exécution de code arbitraire.

La bonne nouvelle, c'est que cette attaque classique se neutralise entièrement au niveau du serveur web, indépendamment de la faille d'origine qui a permis le dépôt du fichier. Une seule règle de configuration, posée une fois pour toutes, ferme cette porte pour n'importe quelle extension présente ou future sur le site.

## Pourquoi ce dossier précisément

WordPress n'a normalement aucune raison d'exécuter du PHP situé dans `wp-content/uploads` : ce répertoire est censé ne contenir que des images, documents et autres médias, jamais de code applicatif. Autoriser malgré tout ce dossier à exécuter du PHP par défaut, comme le font de nombreuses configurations serveur sorties d'usine, revient à laisser une porte ouverte qui ne sert jamais en usage normal, mais qui devient critique le jour où un attaquant trouve un moyen d'y déposer un script, que ce soit via une faille d'upload dans une extension, une vulnérabilité d'import de fichiers ou un accès FTP compromis.

## La règle sous nginx

Sous nginx, il suffit d'ajouter un bloc de localisation qui intercepte toute tentative d'exécution de PHP dans ce dossier avant qu'elle n'atteigne le gestionnaire FastCGI habituel :

```
location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}
```

Ce bloc doit être placé avant la configuration générale qui transmet les fichiers `.php` à PHP-FPM, afin que nginx l'évalue en priorité. Un rechargement de la configuration suffit à l'activer :

```
nginx -t && systemctl reload nginx
```

> L'essentiel à retenir : uploads reçoit des fichiers d'origine externe, jamais du code de confiance ; Une règle serveur suffit à neutraliser un script PHP déposé ; Vérifiable en une requête avec un fichier test inoffensif

## La règle sous Apache

Sous Apache, la même protection passe par un fichier `.htaccess` déposé directement dans `wp-content/uploads`, ou par un bloc équivalent dans la configuration principale du site :

```
<FilesMatch "\.php$">
    Require all denied
</FilesMatch>
```

Sur les versions d'Apache antérieures à 2.4, la syntaxe diffère légèrement et utilise `Deny from all` à la place de `Require all denied`. Il convient de vérifier la version active avec `apache2 -v` avant de choisir la syntaxe adaptée.

## Vérifier que la règle fonctionne réellement

Une règle mal placée ou mal interprétée peut donner une fausse impression de sécurité. La méthode la plus fiable pour vérifier consiste à déposer volontairement, en environnement de test, un fichier PHP inoffensif :

```
echo '<?php echo "test-execution"; ?>' > wp-content/uploads/test.php
```

Puis à ouvrir `https://votre-site.test/wp-content/uploads/test.php` dans un navigateur. Deux résultats possibles :

- Le navigateur affiche une erreur 403 ou le contenu brut du fichier sans exécution : la protection fonctionne.
- Le texte « test-execution » s'affiche : le fichier a bien été exécuté par PHP, la règle n'est pas active et mérite d'être corrigée en urgence.

Il ne faut évidemment pas oublier de supprimer ce fichier test une fois la vérification effectuée.

## Ce que cette règle ne remplace pas

Bloquer l'exécution de PHP dans `uploads` ne dispense pas de valider correctement le type et le contenu des fichiers envoyés côté applicatif, ni de maintenir les extensions à jour. C'est une protection en profondeur : même si une faille d'upload venait à exister dans une extension, le pire scénario — l'exécution du fichier déposé — resterait impossible. C'est précisément l'intérêt d'une défense en couches : chaque niveau limite les dégâts si le précédent est franchi.

> Sur tous les sites que nous provisionnons, cette règle fait partie du modèle serveur de base, au même titre que la configuration TLS : elle ne coûte rien en fonctionnement normal et évite un scénario catastrophe.

## En résumé

Interdire l'exécution de PHP dans `wp-content/uploads` est l'une des mesures les plus rentables qui soient : une poignée de lignes de configuration serveur, aucun impact sur le fonctionnement normal du site, et une voie d'attaque entière neutralisée d'un coup, quelle que soit l'extension à l'origine d'une éventuelle faille future.
