Guides Tutoriel

Sécurisation PrestaShop : La checklist complète

Guide complet de sécurité pour PrestaShop : durcissement serveur, protection admin, audit des modules, sécurité base de données et réponse aux incidents.

À quoi ressemble vraiment une boutique PrestaShop compromise

La plupart des boutiques piratées que l'on nous a appelés à nettoyer depuis 2013 paraissaient impeccables depuis la page d'accueil. Le propriétaire ne l'a découvert que parce que Google a signalé le site, parce que le processeur de paiement a gelé les versements, ou parce qu'un client a téléphoné au sujet d'une « redirection bizarre après le passage dans le tunnel de commande ». À ce stade, l'attaquant était généralement à l'intérieur depuis des semaines.

Les schémas se répètent. Un module tiers vulnérable laisse fuiter la base de données. Une URL d'administration récupérée par scraping subit une attaque par force brute en un week-end. Un shell PHP déguisé en image atterrit dans img/. Une porte dérobée injecte un voleur de cartes dans order-confirmation.tpl. Rien de tout cela n'est exotique. La liste de contrôle ci-dessous peut aider à réduire ces risques.

Voici la liste de contrôle que nous remettons aux clients avant d'accepter de gérer leur boutique PrestaShop. Les chemins et les versions de PHP varient selon la version de PrestaShop, mais les principes de durcissement restent les mêmes. Pour la version non technique, orientez le propriétaire de la boutique vers notre guide de sécurité en langage clair.

1. Comment les boutiques PrestaShop se font réellement pirater

Injection SQL dans un module tiers

C'est le vecteur numéro un, et de loin. Le cœur est raisonnablement éprouvé ; les modules, eux, ne le sont pas. Un développeur junior livre un contrôleur front-office qui concatène $_GET['id'] directement dans une requête, un scanner automatisé le repère, l'attaquant exporte ps_customer et ps_orders avant midi. Nous l'avons constaté avec des modules issus de la marketplace officielle Addons, pas seulement de forums de versions crackées.

Force brute sur l'administration

PrestaShop ne dispose d'aucune limitation de débit native sur le formulaire de connexion de l'administration. Dès qu'un attaquant connaît votre répertoire d'administration (et il le connaîtra, car la moitié des boutiques que nous auditons utilisent encore /admin/ ou /admin123/), il lancera des milliers de tentatives de mot de passe par minute. Tout compte avec welcome2024 ou le nom de la boutique tombe en quelques minutes.

Utilisez des limites de tentatives de connexion, des blocages par IP et des alertes en cas d’attaque des comptes employés. Ces contrôles complètent les mots de passe robustes et la 2FA ; ils ne les remplacent pas.

Téléversement de fichier vers un shell PHP

Un téléversement de « photo de profil » ou d'« image de produit » qui ne valide pas le contenu réel du fichier, seulement l'extension. L'attaquant téléverse shell.php.jpg, le serveur est configuré pour exécuter tout ce qui correspond à .php dans le chemin, partie terminée. Le correctif côté serveur web (bloquer l'exécution de PHP dans img/, upload/, download/) figure ci-dessous, configurez-le une fois et il neutralise toute une catégorie de mauvais modules.

PHP en fin de vie et logiciels non corrigés

PHP 7.4 est en fin de vie depuis novembre 2022. Nous le voyons encore en production. Chaque exploit publiquement documenté contre PHP 7.x est une victoire gratuite pour un attaquant, et il en va de même pour MySQL 5.7, Apache 2.2 et PrestaShop 1.7.6 avec trois ans de CVE non corrigées.

Fichiers de configuration exposés

Un serveur web mal configuré sert volontiers /.env, /.git/config ou /app/config/parameters.php à quiconque le demande. Mot de passe de la base de données, clé de cookie, nom du dossier d'administration : le tout, en clair, en une seule requête GET. Nous effectuons cette vérification sur chaque boutique que nous prenons en charge.

Mise au point : « Ma boutique est trop petite pour être une cible » est ce que tout propriétaire nous répète avant la facture de nettoyage. Les scanners ne lisent pas votre page À propos, ils balaient chaque adresse IPv4 d'internet à la recherche de signatures PrestaShop. La taille n'a aucune importance.

2. Durcissement au niveau du serveur

Version et configuration de PHP

Exécutez la version de PHP la plus récente que votre version de PrestaShop prend en charge, PHP 8.1+ pour PS 8.x, PHP 8.1–8.4 pour PS 9.x. Si vous êtes bloqué sur une version antérieure à PHP 8.1 à cause d'un module, la solution est de remplacer le module, pas de rester sur une version PHP en fin de vie.

Le durcissement de php.ini que nous appliquons par défaut :

disable_functions = exec,passthru,shell_exec,system,proc_open,popen
expose_php = Off
allow_url_include = Off
display_errors = Off
log_errors = On
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
session.cookie_samesite = Lax
open_basedir = /var/www/html:/tmp:/usr/share/php
Une poignée de modules (anciens processeurs d'images, certains générateurs de PDF) ont réellement besoin de exec(). Ne rouvrez pas toute la liste pour faire fonctionner un seul module. Réactivez la seule fonction qu'il réclame, consignez la décision, et si vous pouvez remplacer le module par un autre qui ne fait pas appel au shell, faites-le lors de la prochaine fenêtre de maintenance.

Permissions des fichiers

Les trois nombres qui comptent :

  • 755 sur les répertoires : le propriétaire peut écrire, tout le monde peut lister et parcourir
  • 644 sur les fichiers : le propriétaire peut écrire, tout le monde peut lire
  • 400 sur app/config/parameters.php : seul le propriétaire peut le lire. Ce fichier contient les identifiants de votre base de données. Traitez-le comme une clé privée.
chown -R www-data:www-data /var/www/html/prestashop
find /var/www/html/prestashop -type d -exec chmod 755 {} \\;
find /var/www/html/prestashop -type f -exec chmod 644 {} \\;
chmod 400 /var/www/html/prestashop/app/config/parameters.php

# Répertoires accessibles en écriture dont PrestaShop a besoin
chmod -R 775 /var/www/html/prestashop/var/cache
chmod -R 775 /var/www/html/prestashop/var/logs
chmod -R 775 /var/www/html/prestashop/img
chmod -R 775 /var/www/html/prestashop/upload
chmod -R 775 /var/www/html/prestashop/download

Si un tutoriel, un article d'assistance ou un service d'aide d'hébergeur vous dit de faire chmod 777 sur quoi que ce soit, ignorez-le et trouvez une meilleure source. Il n'existe aucun scénario où 777 soit la bonne réponse sur une boutique en production.

SSL/TLS et en-têtes de sécurité

Activez le SSL dans Paramètres de la boutique → Général, forcez la redirection au niveau du serveur web et ajoutez HSTS afin que le navigateur refuse de rétrograder.

# .htaccess Apache
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Nginx
server {
    listen 80;
    server_name yourdomain.com;
    return 301 https://$server_name$request_uri;
}
server {
    listen 443 ssl http2;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

Politique de sécurité du contenu (CSP)

La CSP peut atténuer l'impact d'un voleur de cartes injecté ou d'une charge utile XSS, mais une politique stricte sur PrestaShop cassera le tunnel de commande dès le premier essai. Les widgets de paiement, l'analytique, le chat, les polices et de nombreux scripts JavaScript de modules se chargent depuis des origines tierces. Déployez-la en deux étapes :

# Apache : surveillez d'abord, n'appliquez pas immédiatement
Header always set Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; connect-src 'self' https:; frame-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-report"
# Nginx : surveillez d'abord, n'appliquez pas immédiatement
add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; connect-src 'self' https:; frame-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-report" always;

Laissez-la en Report-Only pendant au moins une semaine de trafic réel. Collectez les violations, remplacez le caractère générique https: par les domaines réels de vos prestataires (Stripe, PayPal, Adyen, Klarna, GA, GTM, Hotjar, etc.) et ne passez à l'application qu'une fois qu'un test complet du tunnel de commande s'est déroulé sans accroc. Conservez 'unsafe-inline' aussi longtemps que votre thème en a besoin, le retirer exige la prise en charge des nonces ou des empreintes dans chaque modèle.

Bloquer le listage des répertoires et les fichiers sensibles

Les règles Apache que nous utilisons pour chaque boutique que nous hébergeons : placez-les dans le fichier .htaccess à la racine de la boutique, à l'exception des blocs <Directory>, qui doivent figurer dans la configuration du serveur ou de l'hôte virtuel :

Options -Indexes

# Bloquer les types de fichiers sensibles
<FilesMatch "\\.(env|yml|yaml|log|sql|bak|old|orig|save|swp|dist|config|ini|phps)$">
    Require all denied
</FilesMatch>

# Bloquer les fichiers et répertoires cachés (.git, .env, etc.)
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule (^\\.|/\\.) - [F]
</IfModule>

# Bloquer les fichiers composer
<FilesMatch "^(composer\\.json|composer\\.lock)$">
    Require all denied
</FilesMatch>

# Bloquer les répertoires config, vendor et log
<IfModule mod_rewrite.c>
    RewriteRule ^config/ - [F]
    RewriteRule ^vendor/ - [F]
    RewriteRule ^var/logs/ - [F]
    RewriteRule ^app/config/ - [F]
</IfModule>

# Bloquer l'exécution de PHP dans les répertoires de téléversement
<Directory "/var/www/html/prestashop/upload">
    <FilesMatch "\\.ph(p[3457]?|t|tml)$">
        Require all denied
    </FilesMatch>
</Directory>

<Directory "/var/www/html/prestashop/img">
    <FilesMatch "\\.ph(p[3457]?|t|tml)$">
        Require all denied
    </FilesMatch>
</Directory>

Équivalent Nginx :

location ~* \\.(env|yml|yaml|log|sql|bak|old|swp|dist|config|ini)$ { deny all; return 404; }
location ~ /\\. { deny all; return 404; }
location ~* ^/(upload|img|download)/.*\\.php$ { deny all; return 404; }
location ~* ^/(config|vendor|var/logs|app/config)/ { deny all; return 404; }
autoindex off;
Vérifiez-le. Ouvrez https://yourshop.com/.env et https://yourshop.com/app/config/parameters.php dans une fenêtre de navigation privée après le déploiement. Un code 403 ou 404 est correct. Tout autre résultat et vous distribuez vos identifiants.

3. Durcissement du panneau d'administration

Paramètres de sécurité dans le Back Office de PrestaShop 8.

La protection par jeton et la politique de mot de passe sont les deux paramètres présents ici. La protection par jeton doit rester activée ; le score du mot de passe doit être d'au moins 3.

Page Sécurité du Back Office de PrestaShop 8 montrant le commutateur de protection par jeton et les paramètres de la politique de mot de passe

Renommer le répertoire d'administration : correctement

PrestaShop installe par défaut un dossier d'administration aléatoire. Si le vôtre est toujours /admin/ ou un mot devinable (/backoffice, /panel, le nom de la boutique, les initiales du développeur), renommez-le dès aujourd'hui avec dix caractères aléatoires ou plus :

mv /var/www/html/prestashop/admin /var/www/html/prestashop/admin-x7k9m2p4
rm -rf /var/www/html/prestashop/var/cache/*

Ce n'est pas une sécurité en soi, c'est la différence entre figurer sur la liste de cibles de chaque scanner et ne pas y figurer. Mettez la nouvelle URL en favori, conservez-la dans votre gestionnaire de mots de passe et passez à autre chose.

Mots de passe forts et 2FA : pas optionnels

Chaque compte administrateur : 16 caractères ou plus, généré par un gestionnaire de mots de passe, jamais réutilisé. PrestaShop 1.7.6 et les versions ultérieures prennent en charge le TOTP (Google Authenticator, Authy, 1Password, Bitwarden) nativement dans Paramètres avancés → Administration. Activez-le pour chaque employé, sans aucune exception. Ce simple commutateur déjoue l'écrasante majorité des attaques par force brute et par credential stuffing que nous observons.

Security Revolution impose la 2FA, audite le durcissement des comptes employés et fait remonter les comptes qui ont dérivé hors de la politique. La règle de base, avec ou sans le module, reste la même : la 2FA activée sur chaque compte capable d'atteindre /admin/.

Restreindre l'administration par IP si vous le pouvez

Si votre équipe travaille depuis une IP de bureau fixe ou un VPN, verrouillez l'administration sur ces adresses :

# .htaccess à l'intérieur du répertoire d'administration
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REMOTE_ADDR} !^203\\.0\\.113\\.10$
    RewriteCond %{REMOTE_ADDR} !^198\\.51\\.100\\.20$
    RewriteRule .* - [F,L]
</IfModule>

Le VPN uniquement est le point idéal : les employés peuvent travailler depuis n'importe quel café d'Europe, l'administration rejette quand même tous les autres au niveau du serveur web avant même que le code de connexion de PrestaShop ne s'exécute. Lorsque les abus proviennent d'IP de clients ou de visiteurs récurrents plutôt que d'attaques fixes sur l'administration, Customer Extra Info & IP Ban offre au personnel d'assistance une voie de révision et de blocage plus sûre que la modification manuelle des règles du serveur web.

Élaguer les comptes employés

Ouvrez Paramètres avancés → Équipe → Employés dès maintenant. Chaque compte est un identifiant susceptible d'être hameçonné. Supprimez :

  • Toute personne ayant quitté l'entreprise il y a plus de 30 jours
  • Les comptes de test que le développeur initial a créés puis oubliés
  • Les prestataires dont le projet est terminé

Et rétrogradez quiconque n'a pas besoin du profil SuperAdmin. Le personnel d'entrepôt n'a pas besoin de réinitialiser la clé de cookie. Le service client n'a pas besoin d'installer des modules.

Fail2ban sur le point de terminaison de connexion

# /etc/fail2ban/filter.d/prestashop-admin.conf
[Definition]
failregex = ^<HOST> -.*"POST .*/admin.*/index\\.php\\?controller=AdminLogin.*" (200|302)

# /etc/fail2ban/jail.d/prestashop.conf
[prestashop-admin]
enabled = true
filter = prestashop-admin
logpath = /var/log/apache2/access.log
maxretry = 5
findtime = 600
bantime = 3600

Fail2ban surveille les journaux du serveur. Pour les formulaires destinés aux clients où les robots ne touchent jamais le point de terminaison de l'administration, reCAPTCHA & hCaptcha Protection ajoute la couche de vérification avant que le spam ne devienne un abus de compte, de formulaire de contact ou d'inscription.

4. Sécurité des modules

Les modules constituent la plus grande surface d'attaque unique de toute installation PrestaShop. Traitez chacun d'eux comme du code non fiable s'exécutant avec un accès complet à la base de données jusqu'à preuve du contraire.

Où se procurer des modules, et où ne pas le faire

Sources acceptables : la marketplace officielle PrestaShop Addons, les éditeurs établis disposant d'un historique public, et les projets open source bien entretenus sur GitHub où vous pouvez lire le code vous-même. Partout ailleurs, c'est un risque.

Les modules crackés vous feront pirater. Ce n'est pas une hypothèse. Celui qui a craqué le module y a ajouté une porte dérobée avant de le re-téléverser, c'est tout l'intérêt de l'opération. Nous avons nettoyé des boutiques où un seul module « téléchargement gratuit » cracké exfiltrait silencieusement chaque commande vers un tiers pendant six mois. Aucune exception, aucun « je vais juste l'utiliser en préproduction ». Cela finit en production.

Auditer le code d'un module avant de l'installer

Ouvrez le ZIP. Recherchez ces éléments avec grep :

# Dangereux : exécution de code arbitraire
eval($variable)
eval(base64_decode($something))
assert($user_input)

# Dangereux : chargement de code distant
file_get_contents('http://external-domain.com/...')
include('http://...')

# Dangereux : SQL non assaini
"SELECT * FROM ps_table WHERE id = " . $_GET['id']
Db::getInstance()->execute("... " . $_POST['value'] . " ...")

À quoi ressemble un code de module propre :

// SÛR : conversion en entier, utilisation de pSQL()
$id = (int)Tools::getValue('id');
$name = pSQL(Tools::getValue('name'));

Si vous n'avez ni le temps ni les bases en PHP pour réaliser un audit, vérifiez au moins si le développeur possède une page d'avis de sécurité, publie des journaux de modifications et répond aux tickets. Le silence après une CVE est un signal d'alerte.

Maintenez-les à jour

  • Vérification hebdomadaire des mises à jour de modules au minimum
  • Abonnez-vous à la liste de diffusion de sécurité de votre éditeur
  • Suivez Friends of Presta pour les CVE des modules PrestaShop, c'est ce qui se rapproche le plus d'un flux de divulgation coordonnée dans l'écosystème
  • Sauvegardez avant chaque mise à jour. Toujours.

Désactiver n'est pas supprimer

Les fichiers PHP d'un module désactivé sont toujours sur le disque et ses contrôleurs front-office restent accessibles par URL directe. S'il présente une injection SQL, le désactiver ne change rien. Le seul état sûr est qu'il ait disparu :

# Désinstallez via le Back Office, puis supprimez les fichiers
rm -rf /var/www/html/prestashop/modules/unused_module

Ouvrez votre liste de modules et faites-le maintenant. Chaque module que vous avez testé en 2022 et jamais utilisé constitue un risque inutile.

Permissions sur le répertoire des modules

find /var/www/html/prestashop/modules -type d -exec chmod 755 {} \\;
find /var/www/html/prestashop/modules -type f -exec chmod 644 {} \\;

5. Sécurité de la base de données

N'exécutez pas PrestaShop en tant que root

L'utilisateur de base de données dans parameters.php devrait avoir exactement les permissions dont PrestaShop a besoin, et rien de plus :

CREATE USER 'prestashop_user'@'localhost' IDENTIFIED BY 'long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
      CREATE TEMPORARY TABLES, LOCK TABLES
      ON prestashop_db.* TO 'prestashop_user'@'localhost';
FLUSH PRIVILEGES;

Quand une injection SQL frappe (et sur une boutique de 50 modules, cela finira par arriver), un utilisateur au périmètre restreint fait la différence entre « une seule base de données exportée » et « toutes les bases de données du serveur exportées, lecture de /etc/passwd via LOAD_FILE et écriture d'un webshell via INTO OUTFILE ».

Des sauvegardes qui fonctionnent vraiment

# Entrées crontab
# Sauvegarde de la base de données : quotidienne à 3 h
0 3 * * * mysqldump -u backup_user -p'password' prestashop_db | gzip > /backups/db/ps_$(date +\\%Y\\%m\\%d).sql.gz

# Sauvegarde des fichiers : quotidienne à 3 h 30
30 3 * * * tar -czf /backups/files/ps_files_$(date +\\%Y\\%m\\%d).tar.gz /var/www/html/prestashop/

# Nettoyage des sauvegardes de plus de 30 jours
0 4 * * * find /backups/ -name "*.gz" -mtime +30 -delete

Les règles que nous avons apprises à la dure :

  • Hors serveur. Les sauvegardes sur la même machine sont supprimées par le même attaquant qui a supprimé les originaux. S3, un second VPS, n'importe où avec des identifiants distincts.
  • Testez la restauration chaque mois. Des sauvegardes non testées sont des histoires, pas une assurance. Restaurez vers un conteneur de préproduction et chargez la page d'accueil.
  • Chiffrez-les avant qu'elles ne quittent le serveur. Les exports SQL contiennent les données personnelles des clients et les empreintes de mots de passe. gpg ou age, les clés résidant à un endroit que vous seul et une autre personne pouvez atteindre.
  • 30 jours de rétention minimum. Certaines compromissions ne se révèlent que des semaines plus tard. Une rotation sur 7 jours ne vous sauvera pas.

phpMyAdmin : supprimez-le, ou confinez-le

Notre position par défaut est de ne pas l'installer du tout en production. Un tunnel SSH fait le même travail sans exposer une vaste surface d'attaque basée sur le web :

# Depuis votre machine LOCALE
ssh -L 3307:localhost:3306 user@yourserver.com
# Connectez ensuite votre client MySQL local à localhost:3307

Si vous devez conserver phpMyAdmin : chemin d'URL aléatoire, restriction par IP, authentification HTTP Basic en amont et connexion root désactivée :

$cfg['Servers'][$i]['AllowRoot'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;

6. Surveillance et détection

Surveillance de l'intégrité des fichiers

Un attaquant déjà présent modifiera des fichiers, webshell dans img/, voleur de cartes dans un modèle, administrateur supplémentaire dans ps_employee. Une vérification quotidienne des empreintes attrape la moitié « fichiers » de ce problème :

#!/bin/bash
# /usr/local/bin/prestashop-integrity-check.sh
SHOP_DIR="/var/www/html/prestashop"
BASELINE="/var/backups/prestashop-file-hashes.txt"
CURRENT="/tmp/prestashop-file-hashes-current.txt"
ALERT_EMAIL="admin@yourdomain.com"

find "$SHOP_DIR" -type f \\
    -not -path "*/var/cache/*" \\
    -not -path "*/var/logs/*" \\
    -not -path "*/img/p/*" \\
    -not -path "*/img/c/*" \\
    -exec md5sum {} \\; | sort > "$CURRENT"

if [ -f "$BASELINE" ]; then
    DIFF=$(diff "$BASELINE" "$CURRENT")
    if [ -n "$DIFF" ]; then
        echo "$DIFF" | mail -s "ALERT: PrestaShop files modified" "$ALERT_EMAIL"
    fi
fi

Générez la référence juste après un déploiement propre, planifiez le script quotidiennement et affinez les exclusions jusqu'à ne recevoir d'alertes que sur de vrais changements. Attendez-vous à du bruit la première semaine.

Security Revolution regroupe ce contrôle et quelques autres si vous préférez ne pas maintenir vous-même un script cron et un fichier de référence.

Surveillance des journaux

# Tentatives d'injection SQL
grep -iE "(union\\s+select|or\\s+1=1|information_schema)" /var/log/apache2/access.log

# Tentatives d'inclusion de fichier
grep -iE "(etc/passwd|\\.\\.\\/\\.\\.\\/)" /var/log/apache2/access.log

# Accès direct aux fichiers de module (tentatives d'exploitation potentielles)
grep -E "modules/.*/ajax|modules/.*/api" /var/log/apache2/access.log

Un cron nocturne qui envoie les correspondances par e-mail est la version économique. Envoyer les journaux vers Graylog, Loki ou Papertrail et alerter sur des motifs est la version aboutie.

Surveillance de la disponibilité : vérification du contenu, pas seulement d'un code HTTP 200

  • UptimeRobot, HetrixTools ou Uptime Kuma auto-hébergé : tous conviennent
  • Surveillez la page d'accueil et le tunnel de commande, une compromission partielle ne tue souvent que le flux de commande
  • Vérifiez la présence d'un texte de page précis (« Ajouter au panier », le nom de votre boutique), pas seulement une réponse 200. Une boutique défigurée renvoie quand même 200.
  • Intervalles de 1 à 5 minutes, alertes par SMS ou Slack, l'e-mail seul finit enterré

Alertes de connexion à l'administration

Sessions des employés dans PrestaShop 8.

Cette page affiche chaque session d'administration active avec le nom de l'employé, l'e-mail et l'horodatage de la dernière activité. Si vous soupçonnez une connexion non autorisée, c'est le premier endroit à vérifier.

Page Sessions des employés de PrestaShop 8 montrant les sessions d'administration actives avec horodatages et détails des employés

Un petit module sur mesure greffé sur l'événement post-connexion envoie un e-mail à la sécurité chaque fois que quelqu'un se connecte. Peu coûteux à livrer, il vous indique instantanément si un identifiant a fuité :

public function hookActionAdminLoginControllerLoginAfter($params)
{
    $employee = $params['employee'];
    $ip = Tools::getRemoteAddr();

    Mail::Send(
        (int)Configuration::get('PS_LANG_DEFAULT'),
        'alert_admin_login',
        "Admin Login: {$employee->email} from {$ip}",
        ['{body}' => "Employee: {$employee->email}
IP: {$ip}
Time: " . date('Y-m-d H:i:s')],
        'security@yourdomain.com',
        'Security Alert'
    );
}

7. Vous avez été piraté. Et maintenant.

Les 30 premières minutes

  • Ne supprimez rien pour l'instant. L'état compromis est une preuve médico-légale. Vous en aurez besoin pour trouver le point d'entrée.
  • Mettez la boutique hors ligne avec une page de maintenance ou une barrière par mot de passe temporaire, stoppez l'hémorragie immédiatement.
  • Renouvelez chaque identifiant. SSH, FTP, base de données, chaque compte administrateur, panneau d'hébergement, clés d'API de la passerelle de paiement, tout ce qui est stocké dans le fichier parameters.php compromis.
  • Réalisez un instantané de l'état compromis (tar complet + mysqldump) et étiquetez-le. Vous en aurez besoin pour l'analyse une fois la poussière retombée.
  • Téléphonez à votre processeur de paiement si vous traitez directement des données de cartes. Il préfère l'apprendre de vous en premier.
# Mode maintenance rapide
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^YOUR\\.IP\\.ADDRESS$
RewriteCond %{REQUEST_URI} !^/maintenance\\.html$
RewriteRule .* /maintenance.html [R=503,L]

Trouver la porte dérobée : ils en laissent toujours une

Nettoyer les dégâts visibles sans trouver le mécanisme de persistance vous fait recompromettre en une semaine. Les endroits où chercher :

# Rechercher des motifs de porte dérobée
grep -rn "eval(" /var/www/html/prestashop/ --include="*.php" | grep -v "vendor\\|cache"
grep -rn "base64_decode" /var/www/html/prestashop/ --include="*.php" | grep -v "vendor\\|cache"
grep -rn "shell_exec\\|passthru\\|system(" /var/www/html/prestashop/ --include="*.php" | grep -v "vendor\\|cache"

# Trouver les fichiers PHP modifiés récemment
find /var/www/html/prestashop/ -name "*.php" -mtime -7 -not -path "*/cache/*"

# Trouver les fichiers PHP dans des répertoires où ils ne devraient pas exister
find /var/www/html/prestashop/img/ -name "*.php"
find /var/www/html/prestashop/upload/ -name "*.php"

# Vérifier la présence de code obscurci (lignes uniques très longues)
find /var/www/html/prestashop/ -name "*.php" -exec awk 'NR==1 && length>5000' {} +

Ne vous arrêtez pas au système de fichiers, les attaquants persistent aussi via la base de données :

SELECT id_cms, meta_title FROM ps_cms_lang WHERE content LIKE '%<?php%' OR content LIKE '%eval(%';
SELECT * FROM ps_employee ORDER BY date_add DESC LIMIT 10;

Cette seconde requête attrape un grand classique : l'attaquant crée son propre compte administrateur afin de conserver l'accès après que vous avez changé tous les mots de passe.

Récupération

  1. Trouvez le point d'entrée dans les journaux d'accès. Cherchez des requêtes POST inhabituelles vers modules/*/ajax.php ou modules/*/api.php autour du moment où le contrôle d'intégrité a signalé un changement pour la première fois.
  2. Restaurez depuis une sauvegarde réputée propre si elle existe et qu'elle est antérieure à la compromission.
  3. Si aucune sauvegarde propre : remplacez tous les fichiers du cœur par un téléchargement neuf de votre version exacte de PS, réinstallez chaque module depuis sa source d'origine, ne conservez que votre thème et le répertoire img/ après les avoir scannés minutieusement.
  4. Scannez la base de données à la recherche de contenu injecté dans ps_configuration, ps_cms_lang et ps_meta_lang. Les voleurs de cartes en raffolent.
  5. Corrigez tout : cœur, modules, PHP, MySQL, OS. Ne remettez pas la boutique en ligne sur le même logiciel qui les a laissés entrer.

Après le nettoyage

  • Corrigez la vulnérabilité précise qui a été exploitée. Désactiver le mauvais module n'est pas la corriger, supprimez-le ou corrigez-le.
  • Surveillez plus étroitement pendant les 30 premiers jours. Ils tenteront de revenir.
  • Un WAF placé devant la boutique (l'offre gratuite de Cloudflare est un point de départ raisonnable) attrape bon nombre des mêmes scanners au passage suivant.
  • Si des données de clients ou de paiement ont pu être exposées, parlez à un avocat de la notification de violation au titre du RGPD. Un compte à rebours de 72 heures est lancé.
Vérité difficile : Si vous ne parvenez pas à déterminer comment ils sont entrés, partez du principe qu'ils entreront à nouveau. Un audit professionnel ponctuel coûte bien moins cher qu'une seconde violation, à laquelle s'ajoutent les retombées réglementaires.

8. La liste de contrôle

Imprimez-la et parcourez-la. Chaque case non cochée est une porte d'entrée.

Serveur et PHP

  • Version de PHP à jour et prise en charge
  • Fonctions PHP dangereuses désactivées
  • expose_php = Off
  • display_errors = Off en production
  • allow_url_include = Off
  • Cookies de session : HttpOnly, Secure, SameSite
  • open_basedir défini
  • OS, MySQL, serveur web à jour
  • Authentification SSH par clé activée, authentification par mot de passe désactivée
  • Pare-feu, uniquement les ports dont vous avez besoin

Système de fichiers

  • Répertoires en 755, fichiers en 644
  • parameters.php en 400
  • Rien en 777
  • Exécution de PHP bloquée dans upload/, img/, download/
  • Listage des répertoires désactivé
  • .env, .git, fichiers YAML et de configuration tous bloqués depuis le web
  • vendor/ et var/logs/ bloqués depuis le web

SSL et HTTPS

  • Certificat valide avec renouvellement automatique
  • Redirection HTTP→HTTPS au niveau du serveur web
  • En-tête HSTS défini
  • SSL activé pour toutes les pages dans PrestaShop
  • Aucun avertissement de contenu mixte

Panneau d'administration

  • Le répertoire d'administration est une chaîne aléatoire
  • Tous les mots de passe de 16 caractères ou plus issus d'un gestionnaire de mots de passe
  • 2FA activée sur chaque compte, sans exception
  • Administration restreinte par IP lorsque c'est faisable
  • Comptes inutilisés supprimés, anciens employés retirés
  • Chaque employé sur un profil au moindre privilège
  • fail2ban ou équivalent sur le point de terminaison de connexion

Modules

  • Chaque module issu d'une source de confiance
  • Zéro module cracké
  • Tous les modules à jour
  • Modules inutilisés supprimés, pas seulement désactivés
  • Code des modules contrôlé par sondage à la recherche de eval() et de SQL non assaini
  • Abonné aux avis de sécurité de vos éditeurs

Base de données

  • Utilisateur de base de données dédié, pas root
  • Permissions minimales requises uniquement
  • Mot de passe de base de données de 20 caractères ou plus
  • MySQL lié à localhost
  • phpMyAdmin supprimé ou restreint par IP
  • Préfixe de table modifié par rapport à la valeur par défaut ps_

Sauvegardes

  • Export quotidien de la base de données automatisé
  • Sauvegarde quotidienne des fichiers automatisée
  • Sauvegardes stockées hors serveur
  • Sauvegardes chiffrées avant le transfert
  • Rétention de 30 jours ou plus
  • Restauration testée au cours des 30 derniers jours

Surveillance

  • Contrôles d'intégrité des fichiers en cours d'exécution
  • Journaux d'accès analysés pour détecter les motifs d'attaque
  • Surveillance de la disponibilité avec vérification d'une chaîne de contenu
  • Alertes de connexion à l'administration actives
  • En-têtes de sécurité présents dans chaque réponse

Préparation aux incidents

  • Plan de réponse aux incidents consigné par écrit
  • Contacts de l'hébergeur et du processeur de paiement à portée de main
  • Processus de notification RGPD documenté
  • Page de maintenance prête à déployer
  • Chaque identifiant critique dans un gestionnaire de mots de passe

La sécurité est une tâche de maintenance, pas un projet. Mettez un rappel trimestriel dans votre calendrier pour reparcourir cette liste. La première fois vous prendra une journée. Ensuite, ce sera une heure. Commencez par le haut : mettez tout à jour, activez la 2FA sur chaque compte, supprimez les modules que vous n'utilisez pas, mettez en place des sauvegardes hors serveur. Le reste suit.

Lectures associées

Questions liées

Chargement...
Retour en haut