Une approche simple pour limiter le spam dans les forums sous SPIP : l’ajout d’un contrôle manuel : sorte de captcha au format texte.
Les captcha sont en général des graphiques voulant représenter plus ou moins lisiblement un mot, un code à recopier dans un champ (voir la page Wikipedia consacrée au captcha).
En réalisant la mise à jour de Quesaco en SPIP 2.1.1, j’ai replacé les formulaires de la distribution. Moins d’une heure après la mise à jour, un petit message commençant par un remerciement en anglais, suivi d’une trentaine de liens sur des sites ... découverte de la nature, des choses de la vie. Le grand classique !
Et ce même type de message posté régulièrement, toutes les heures, d’une adresse IP différente, d’un pays différent, avec une adresse mail et une intro différentes.
Première solution, proposée ici : s’assurer que c’est un humain qui poste en demandant une confirmation : le résultat d’une opération.
Ce n’est pas forcément la bonne solution. Est-ce qu’il y en a une ? Vos propositions et remarques seront les bienvenues.
Et pourquoi ne pas utiliser un captcha graphique ?
D’aucuns pensent que la mise en place d’un captcha graphique rend le site inaccessible aux handicapés visuels. C’est souvent vrai, et bien souvent inaccessible aux personnes âgées, aux personnes qui ne sont pas habituées à répondre à une question qui n’a rien à voir avec le présent formulaire. On parle de handicap cognitif, de hors-contexte, ou de ce que vous voulez, mais en tout cas, mettre en place un captcha graphique et le plus sûr moyen de se débarrasser d’une bonne partie de ses visiteurs un tant soit peu méfiants, impatients.
Vous me direz « Oui, mais un captcha-texte est aussi hors-contexte ». Exact ! Mais il ne romps pas la méthode de communication (je commence ma phrase en texte, je ne la termine pas en image). C’est déjà un début.
Le formulaire du forum SPIP
Le formulaire pour le forum est constitué de deux fichiers :
- formulaires/forum.html
- formulaires/forum.php
Première étape : recopier ces deux fichiers dans le dossier formulaires des squelettes du site.
Modification de forum.html. Un diff :
25a26
> <input type='hidden' name='captcha' value="#ENV{captcha}" />
71a73,76
> <li><p class='explication'>Anti-spam: merci de compléter l'opération :
> <span class="captcha-ope">#EVAL{PETIT_CAPTCHA_OPE} </span>
> <input type="text" class="text" name="captcha" id="captcha"[ value="(#ENV{captcha})"] size="3" />
> [ (#ENV**{erreurs}|table_valeur{captcha}|oui) <span class="captcha-err">Erreur</span>]</p></li>Modification de forum.php. Encore un diff :
12a13,15
> define('PETIT_CAPTCHA_OPE', 'un + un = ');
> define('PETIT_CAPTCHA_RES', serialize(array(2, 'deux')));
>
104a108
> 'captcha' => _request('captcha'),
234a239,243
>
> if(!in_array(trim(_request('captcha')), unserialize(PETIT_CAPTCHA_RES))){
> $erreurs['captcha'] = 'Résultat erroné';
> }
> Les deux fichiers pour les réfractaires du diff (que je comprends) :
Optimisation ou personnalisation
Deux constantes sont à disposition : PETIT_CAPTCHA_OPE et PETIT_CAPTCHA_RES.
La première indique l’opération à réaliser par le visiteur, la seconde la réponse attendue.
L’opération peut très bien être une question du style « Combien y-a-t-il de couleurs dans l’arc-en-ciel ? ». La réponse est 7. Pour cet exemple, modifier les deux constantes du fichier forum.php :
define('PETIT_CAPTCHA_OPE', 'Combien y-a-t-il de couleurs dans l'arc-en-ciel ?');
define('PETIT_CAPTCHA_RES', serialize(array(7)));Un traceur pour debug et optimisation
Dans la version du 17/08/2010 du script joint se trouve un traceur. Il permet d’exporter les données du formulaire (_GET et _POST, dans le sens ou la fonction SPIP _request() cherche les données postées dans cet ordre), dans les 3 étapes CVT, dans un fichier /tmp/formulaire_post.log. Attention, le fichier n’est pas purgé. Si vous activez le trace de cette fonciton, ne pas oublier de faire le ménage de temps en temps. Quand un disque dur sature, c’est la panne assurée.
Historique d’un spam
Le filtre ci-dessus a été mis en place. Le résultat en a été radical. Mais ne doutons pas de la volonté du vilain.
Il y a probablement d’autres spammeurs, qui eux, sont arrêtés par le champ ’nobot’. C’est à vérifier. C’est pour cette raison que je n’ai pas voulu modifier le comportement de ce champ et ajouter un autre pour la fonctionnalité illustrée ici.
Histoire de mieux comprendre la stratégie adoptée par ce spammeur, voici l’historique des interventions :
- 12 août 2010 à 15h33min : mise en place du filtre “(2 + 2 =)”. Le ’=’ fait partie du filtre afin d’éviter un simple eval().
- 13 août 2010 à 19h56min : retour d’un spam. Construction très proche des précédents, mais visiblement pas le même créateur. Ceux reçus il y a quelques jours commençaient tous par une phrase compréhensible (« Congrats to all of you », « That’s so awesome ! So very happy for you ! », etc) suivi d’une trentaine de liens. Dans celui reçu ce jour, le contenu du message commence par un assemblage aléatoire de lettres du style « zdwzkzxlmgyq » suivi seulement de trois liens. Visiblement, un humain qui va mettre en place son automate. Car deux heures plus tard, c’est toujours le plus grand calme.
- 14 août 2010 à 20h57min : retour en masse, une quinzaine reçus en quelques heures, du style du dernier reçu (début aléatoire). Les derniers envois étaient espacés au quart d’heure.
- 15 août 2010 à 8h17min : modification du filtre pour “(3 + 3 =)” histoire de stopper l’hémorragie. Visiblement ça fonctionne.
- 15 août 2010 à 10h05min : le retour. Toujours le même. 2 spams simultanés. Idem 1 heure plus tard. Et encore une heure plus tard au lieu de 1 toutes les 10 minutes. Modification de stratégie ou stratégie de post aléatoire ? Peut-être simplement temps-machine ? En tous cas, ça veut dire qu’il interprête la question. A priori.
- 15 août 2010 à 12h57min modification du filtre pour “un + un = (en chiffre) ”, et du résultat attendu.
- 17 août 2010 à 16h18min. Sans crier victoire, le calme semble revenu. Un seul post reçu hier, probablement humain. Et là, ça nécessite d’autres mesures (nombre d’URL dans le texte, ratio texte/URL, à voir). Le filtre est maintenant simplifié, la réponse attendue est soit un chiffre, soit un texte.
- 17 août 2010 à 18h38min. Correction des exemples ci-dessus et des fichiers mis à disposition. Le précédent exemple est disponible en bas de page, documents joints.
- A suivre...
A lire (si besoin) :
