# **Sécurité idéale** — stack Ubuntu + Apache + WordPress (serveur dédié)

> **Checklist vivante — état au 2026-06-25.** Légende : 🟢 fait · 🟠 partiel/à consolider · 🔴 à faire.
> Détails techniques et rollback : `security/SECURITY-05-durcissement-reseau.md`. Snapshots conf : `snapshots/security/`.

## Tableau de bord

| # | Élément | Couche | Statut |
|---|---------|--------|--------|
| 1 | UFW (pare-feu ports) | Réseau | 🟢 actif, deny in, 22/80/443 |
| 2 | Hardening SSH (clé only + limites + algos) | Réseau | 🟢 fait (PermitRootLogin `no` = reste à basculer) |
| 3 | Fail2ban (SSH + wp-login) | Réseau | 🟢 fait (ban via UFW ; xmlrpc exclu = pause #2) |
| 4 | Blocage xmlrpc.php | WordPress | 🟢 fait (vhost, GET+POST → 403 ; débloqué par le retrait WPML) |
| 5 | Anti-énumération comptes (REST + author) | WordPress | 🟢 fait (mu-plugin) |
| 6 | Permissions fichiers (644/755, pas de 777) | WordPress | 🟢 OK (groupe `jerome` write = à surveiller) |
| 7 | Certbot / SSL | Réseau | 🟢 valide, renouvellement auto |
| 8 | ServerTokens Prod / Signature Off | Apache | 🟢 fait (security.conf : `Server: Apache` sans version) |
| 9 | Security headers (HSTS, X-Frame…) | Apache | 🟠 mod_headers chargé, en-têtes à poser |
| 10 | ModSecurity + OWASP CRS (WAF) | Apache | 🔴 pas installé |
| 11 | ModEvasive (anti-DoS) | Apache | 🔴 pas installé |
| 12 | htpasswd sur wp-admin / wp-login | WordPress | 🔴 à cadrer (impact équipe) |
| 13 | CVE-2024-6386 (WPML) | WordPress | 🟢 FERMÉ — WPML **retiré** (site mono-langue), cf [SECURITY-06](../security/SECURITY-06-retrait-wpml.md) |

## TODO (priorisé) — reste à faire

1. **Security headers** (mod_headers) : HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy. Quick win, à poser dans le vhost.
2. **ModSecurity + OWASP CRS** (WAF) : gros morceau, tuning whitelist admin WP nécessaire.
3. **ModEvasive** : anti-DoS léger.
4. **htpasswd wp-admin / wp-login** : à cadrer avec le client (impact équipe : basic-auth partagé ou allowlist IP).
5. ~~**xmlrpc (#2)**~~ → 🟢 **FAIT** : bloqué au vhost (GET+POST 403). Le retrait WPML a levé la dépendance translationproxy.
6. ~~**WPML MAJ (CVE-2024-6386)**~~ → 🟢 **RÉSOLU autrement** : WPML retiré (site mono-langue), faille éliminée sans licence OTGS. Cf SECURITY-06.
7. **PermitRootLogin `no`** : bascule après validation du workflow `ubuntu`+sudo.

### Mineurs / hygiène
- `ServerName` global Apache (supprime le warning AH00558).
- `ufw limit 22/tcp` (defense-in-depth SSH, complément fail2ban).
- Dossiers webroot en 775 avec groupe `jerome` (humain) en write -> à revoir.
- ~9 plugins obsolètes à MAJ via wp-cli (FILE_MODS bloque l'admin) ; supprimer ACF free (mort).

---

### 1. La Couche Réseau et Système (La Fondation)

- **UFW (Uncomplicated Firewall) :** Le videur de la boîte de nuit. 🟢 **FAIT**
  - *Ce qu'il fait :* Il ferme toutes les portes par défaut.
  - *Configuration :* N'ouvre que les ports **80** (HTTP), **443** (HTTPS) et ton port **SSH** (le 22 par défaut, mais il est fortement conseillé de le changer).
  - *État :* actif (deny incoming), ports 22/80/443 ouverts. Port 22 non changé (optionnel, faible valeur). `ufw limit 22` non posé (mineur).
- **Fail2ban :** Le sniper anti-bruteforce. 🟢 **FAIT (2026-06-25)**
  - *Ce qu'il fait :* Il lit les logs en temps réel et bannit les adresses IP (via UFW) qui font trop d'erreurs.
  - *État :* fail2ban v1.0.2, banaction=`ufw`, jails **[sshd]** (backend systemd, maxretry 4) + **[wordpress-auth]** (filtre custom sur `toulouse.access.log`, POST wp-login.php = HTTP 200 = échec, maxretry 5/5min, ban 2h). ignoreip = loopback + IP serveur. Validé : 2 brute-forceurs SSH bannis (REJECT IN UFW) dès le démarrage.
  - *xmlrpc EXCLU* volontairement (cohérence pause #2 — éviter de bannir IP OTGS si traduction auto WPML). À rebrancher avec la décision xmlrpc.
  - *Confs :* `snapshots/security/fail2ban-jail.local` + `fail2ban-filter-wordpress-auth.conf`.
- **Hardening SSH :** 🟢 **FAIT (2026-06-25)**
  - Connexion par mot de passe désactivée (clé SSH only). 🟢
  - MaxAuthTries 3, LoginGraceTime 30, ClientAliveInterval 300, X11Forwarding/AllowTcpForwarding no, AllowUsers root ubuntu, algos modernes. 🟢
  - `PermitRootLogin no` (interdiction directe root) : actuellement `prohibit-password` (clé only). 🟠 bascule en `no` prévue après validation du workflow `ubuntu`+sudo.

### 2. La Couche Serveur Web (Apache)

C'est ici qu'on bloque les attaques spécifiques aux sites web avant même qu'elles n'atteignent WordPress.

- **ModSecurity (WAF - Web Application Firewall) :** Le détecteur de métaux. 🔴 **PAS INSTALLÉ**
  - *Ce qu'il fait :* C'est un module Apache qui analyse tout le trafic HTTP entrant pour détecter des motifs d'attaques (injections SQL, failles XSS, etc.).
  - *Le combo idéal :* Installe-le avec les règles **OWASP Core Rule Set (CRS)**. Attention : il faudra peut-être mettre certaines règles en liste blanche pour ne pas bloquer des fonctionnalités légitimes de l'admin WordPress.
- **ModEvasive :** L'anti-DDoS de base. 🔴 **PAS INSTALLÉ**
  - *Ce qu'il fait :* Il bloque les requêtes trop rapides et répétées venant d'une même IP (très utile contre les attaques DoS de faible envergure ou les bots aspirateurs très agressifs).
- **Masquage des signatures (Security Headers) :** 🟠 **PARTIEL**
  - Dans ton fichier de configuration Apache (`apache2.conf`), ajoute `ServerTokens Prod` et `ServerSignature Off` pour empêcher Apache de crier sur les toits quelle version exacte tu utilises (ce qui aide les hackers à trouver des failles).
  - *État :* `ServerTokens Prod` + `ServerSignature Off` présents dans le vhost `toulouse.conf`, mais `conf-available/security.conf` dit encore `ServerTokens OS` / `ServerSignature On` → à consolider dans security.conf. En-têtes sécu (HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy) à poser via mod_headers.

### 3. La Couche Applicative (Spécifique WordPress)

Même avec un serveur blindé, WordPress a besoin d'aide au niveau de son architecture de fichiers.

- **Protection du dossier Admin (htpasswd) :** 🔴 **À CADRER**
  - Ajoute une authentification HTTP basique (une popup qui demande un login/mot de passe au niveau du navigateur) sur l'accès à `wp-login.php` ou au dossier `wp-admin` via un fichier `.htaccess` et `.htpasswd`. Cela empêche 99% des bots d'atteindre le script de connexion de WordPress.
  - *Impact :* concerne toute l'équipe (login partagé basic-auth) ou restriction par IP → à décider avec le client.
- **Blocage strict de `xmlrpc.php` :** 🟢 **FAIT (2026-06-25)**
  - Si tu n'utilises pas l'application mobile WordPress ou Jetpack, bloque complètement l'accès à ce fichier directement via ton `.htaccess` ou la conf d'Apache (`<Files xmlrpc.php> Require all denied </Files>`). C'est la plus grande porte d'entrée pour les attaques par déni de service sur WordPress.
  - *✅ FAIT (2026-06-25) :* WPML retiré → plus de translationproxy → blocage total appliqué au vhost 443 (`<Files "xmlrpc.php"> Require all denied </Files>`). GET+POST → 403, site 200. Snapshots `snapshots/apache/`.
- **Gestion stricte des permissions (www-data) :** 🟢 **OK**
  - Assure-toi que les dossiers sont en `755` et les fichiers en `644`. Le propriétaire doit être l'utilisateur d'Apache (`www-data`), mais évite absolument les permissions `777`.
  - *État :* aucun fichier world-writable, propriétaire www-data. 🟠 dossiers en 775 avec groupe `jerome` (humain) en write → à surveiller.

### Le Combo Ultime Résumé :

1. **UFW** (Pare-feu ports) 🟢
2. **Fail2ban** (Bannissement IP dynamique avec filtres SSH + WP-Login ; xmlrpc en pause) 🟢
3. **Clés SSH uniquement** (Pas de mots de passe) 🟢
4. **ModSecurity + OWASP** (WAF pour bloquer les attaques web) 🔴
5. **Protection htaccess** (Double authentification basique sur le wp-admin) 🔴
6. **Let's Encrypt / Certbot** (Certificat SSL obligatoire pour chiffrer les échanges) 🟢
