← Blog

Sécuriser un formulaire de contact en PHP : la checklist 2026

Un formulaire de contact semble anodin. C'est pourtant un vecteur d'attaque classique : spam, injection d'en-têtes, phishing via le champ email, open-redirect, scraping. Voici la checklist que j'applique sur chaque projet.

1. Protection CSRF

Un jeton unique par session, stocké côté serveur, vérifié avec hash_equals() pour éviter les attaques par timing. Rotation du token après chaque soumission valide.

2. Honeypot

Un champ invisible (via CSS ou aria-hidden) que seuls les bots remplissent. Si rempli, on simule un succès mais on jette la soumission. Pas besoin d'informer le bot qu'il a été détecté — il reviendra sinon avec une autre approche.

3. Time check

Un horodatage signé (HMAC) est généré à l'affichage du formulaire. À la soumission, on vérifie que la durée écoulée est au moins 2 secondes (un humain ne remplit pas un formulaire en 500ms) et au plus 1 heure (sinon le token est expiré).

4. Validation + assainissement

Chaque champ est validé strictement : type, longueur min/max, format (regex ou filter_var()), valeurs autorisées pour les listes déroulantes. Les données sont ensuite échappées en sortie avec htmlspecialchars() — jamais avant.

5. Prévention de l'injection d'en-têtes

Sur les champs utilisés dans les en-têtes (From, Reply-To), on supprime tout caractère \r ou \n. Sans cette précaution, un attaquant peut injecter des destinataires cachés (CC/BCC) et transformer votre formulaire en relais de spam.

6. Rate-limiting

À l'échelle d'une PME, un rate-limit par IP stocké en session ou dans un fichier suffit : par exemple 3 soumissions max par heure. Pour les sites plus exposés, passer par fail2ban côté serveur ou un WAF.

Mise en pratique

Les sites Zentik embarquent cette chaîne de sécurité par défaut. Contactez-moi si vous voulez auditer votre formulaire actuel.

À lire aussi