Le spam sur les blogs et les forums

Toute méthode de diffusion d'information qui peut être automatisée est un jour ou l'autre récupérée pour délivrer des messages publicitaires non sollicités : du spam. La multiplication des forums ou des blogs avec leurs commentaires et autres trackback est une bénédiction pour les pourris qui vendent du viagra chinois placébo ou des rollex en taule ondulée.

La première chose à comprendre c'est qu'aucune méthode automatique n'est infaillible. Seule une modération manuelle, par un humain en pleine possession de ses moyens, peut bloquer tout le spam qui serait posté à destination d'un forum ou d'un blog. Ceci posé, voilà quelques conseils pour filtrer un peu la crasse du monde.

Dans 99% des cas, le spammer utilise un outil automatisé pour poster la prose de son client. Ces outils sont de plus en plus perfectionnés et parviennent même à contourner des protections comme les "captcha", ces images représentant des lettres et des chiffres tordus et brouillés que l'utilisateur doit déchiffrer et recopier au clavier dans un champ du formulaire. De nombreux systèmes de "captcha" étaient, ou sont encore, vulnérables à une attaque toute bête : le spammer se connecte une fois manuellement en reconnaissant les chiffres et les lettres lui-même. Il remplit le formulaire, et le valide. Il obtient alors un identifiant de session qu'il va coller dans son script de spam. Le script peut ensuite poster autant de message qu'il veut, sans avoir à valider le test de la captcha. C'est un exemple parfait de porte blindée sur un mur en carton. Moralité, il ne faut pas non plus faire confiance aux systèmes de protection, surtout si on ne sait pas comment ils fonctionnent. Pire, le système de "captcha" est contraignant et même très problématique en terme d'accessibilité. Que devient l'utilisateur malvoyant face à ce blocage ?
Fort heureusement, on voit fleurir quelques systèmes comparables qui ont au moins le soucis de la lisibilité. Certains formulaires, par exemple, sont protégés par des opérations mathématiques du style "combien font deux fois trois en chiffres". L'utilisateur, même si il utilise un terminal braille ou un logiciel de lecture d'écran est à même de répondre à cette question, et donc de poster un message sur le forum ou le blog protégé.

Heureusement, pour le moment, les outils de spam automatiques ont des défauts. Cela ne va pas durer, mais il est encore possible d'utiliser ces faiblesses pour les contrecarrer. Ainsi, l'administrateur attentif, verra dans les logs de son site web des choses intéressantes comme ça :

209.160.72.10 ../.. "POST /blog/tb.php?id=37 HTTP/1.1" 403 112 "-" "-"
209.160.72.10 ../.. "GET /blog/index.php../.. HTTP/1.1" 200 11211 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ../..) ../.. Firefox/1.5.0.4"
209.160.72.10 ../.. "POST /blog/tb.php?id=45 HTTP/1.1" 403 112 "-" "-"
209.160.72.10 ../.. "GET /blog/index.php../.. HTTP/1.1" 200 10770 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ../..) ../.. Firefox/1.5.0.4

C'est un parfait exemple de script de spam codé par un débile. Ce qu'on note immédiatement, c'est le code 403 de retour pour la méthode POST, et le code 200 pour le GET suivant. Je reviendrais la dessus par la suite. On note aussi que le POST est fait avec un "browser" et un "referer" tous deux nuls ("-" "-"), alors que le GET est fait avec un "browser" réglé sur Firefox 1.5.x Windows, première erreur. Seconde erreur, le GET est fait après le POST, quelle idée farfelue : normalement, l'utilisateur charge une page dans son navigateur, puis poste un commentaire sur la page en question, pas l'inverse. Troisième erreur, le navigateur simulé est un Firefox Windows. Or, c'est en contradiction avec le pédigrée de la machine :

$ ssh -v 209.160.72.10
../..
debug1: Connecting to 209.160.72.10 [209.160.72.10] port 22.
debug1: Connection established.
../..
debug1: Remote protocol version 2.0, remote software version OpenSSH_3.8.1p1 FreeBSD-20040419
debug1: match: OpenSSH_3.8.1p1 FreeBSD-20040419 pat OpenSSH_3.*
../..

Un vieux FreeBSD, avec un vieux OpenSSH. Sûrement une machine mal patchée chez un hébergeur peu scrupuleux. C'est rapidement confirmé par un whois. La machine fait partie d'une ferme de serveurs d'hébergement de sites web. Donc en réalité, cette machine ne devrait jamais se connecter à un forum ou un blog pour y poster des commentaires. Quatrième erreur, le script simule un navigateur, mais il ne télécharge pas les images, les scripts javascript, ni les feuilles de styles de la page. C'est peu crédible. Pour finir avec ce cas d'école, le script essaye de poster du spam vers sa cible environ une fois par heure, 24h sur 24, ce n'est pas très réaliste et ça écarte du même coup toute présomption de spam manuel.
Revenons rapidement sur les codes 403 et 200 relevés plus haut. Le code 403 signifie que la requête (POST) à été interdite par le serveur, donc le script n'a pas pu poster son spam. Le code 200 accompagne une réponse favorable à une requête (ici, le GET). Donc le script peut lire la page mais pas poster de commentaires ou de trackback. Pour obtenir ce résultat, il faut bricoler un peu la configuration Apache, soit dans la configuration du serveur, soit via un fichier .htaccess.
Voilà un exemple :

01       ErrorDocument 403 "Due to an heavy spamming problem, you are not allowed to post any data on this blog."
02       # si browser OU referer sont nuls, on trash
03       BrowserMatch ^$ GoAway=1
04       SetEnvIf Referer ^$ GoAway=1
05       # si browser est une escroquerie, on trash
06       BrowserMatch ^PussyCat GoAway=1
07       BrowserMatch ^Opera/8.0$ GoAway=1
08       <LimitExcept GET>
09          Deny from env=GoAway
10       </LimitExcept>

La ligne 1 donne un message personnalisé pour l'erreur 403, au cas où un lecteur légitime se retrouverait bloqué par le système au moment d'envoyer un message ou un commentaire. Les lignes 3 et 4 règlent la variable d'environnement "GoAway" à "1" si le navigateur est nul ou si le "referer" est nul. Les lignes 6 et 7 reprennent deux signatures de navigateurs qui sont bidons et qui sont utilisées par des scripts de spam. De même, si cette signature est trouvée, alors la variable "GoAway" passe à "1".
Le bloc 8-9-10 interdit aux clients dont la variable "GoAway" est définie de faire autre chose que des GET. Donc pour tous les clients qui ont une variable "GoAway" définie, le GET est autorisé, et le POST est interdit (ainsi que le HEAD et les autres méthodes).
Notre client de tout à l'heure, 209.160.72.10, arrive sans "browser" ni "referer", donc le serveur lui attribue une variable "GoAway" à "1". Il ne peut pas faire de POST (erreur 403), mais il peut faire du GET (code 200).

Ceux qui veulent aller moins loin que cela, en interdisant le POST uniquement aux clients qui présentent simultanément un navigateur nul et un "referer" vide, peuvent utiliser ce genre de paramétrage à la place des lignes 2-3-4 ci-dessus :

       # si browser et referer sont nuls en meme temps, on trash
       SetEnvIf Request_URI .* GoAway=1
       BrowserMatch .+ !GoAway
       SetEnvIf Referer .+ !GoAway

Cependant, j'ai moi même renoncé à ce réglage trop permissif.

À ces règles, on peut aussi ajouter une exclusion des gros hébergeurs de serveurs, tels que theplanet.com ou dreamhost.com. Une part non négligeable du spam de blog vient de chez eux, et ils n'ont absolument aucune raison de poster des commentaires car ce sont des serveurs. On ajoute donc sous la ligne 9 tout ou partie de ces "deny" :

          Deny from theplanet.com
          Deny from dreamhost.com
          Deny from leaseweb.com
          Deny from godaddy.com
          Deny from layeredtech.com

Voilà de quoi être relativement tranquille.

Les plus chanceux disposent soit des droits d'administrations complets de leur serveur, soit d'un administrateur qui aura installé mod_geoip sur la machine. Ce module Apache permet de déterminer le pays de connexion pour chaque client. Grace à ce module, il est possible d'interdir l'accès (ou le POST) aux clients dont l'IP de connexion se trouve dans certains pays (Asie, ex-URSS, ...). C'est difficile à justifier pour un très gros forum, mais pour un blog francophone au lectorat assez restreint, c'est une très bonne méthode pour éviter une partie du spam. Voici un exemple d'implémentation :

       ErrorDocument 403 "Due to an heavy spamming problem from some foreign countries, you are not allowed to post any data on this blog."
       GeoIPEnable On
       GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat
       SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
       SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
       SetEnvIf GEOIP_COUNTRY_CODE KR BlockCountry
       # ... place more countries here
       <LimitExcept GET>
          Deny from env=BlockCountry
       </LimitExcept>

Dans cet exemple, les visiteurs de Chine, Russie et Corée peuvent lire le site web, mais pas poster de commentaires/messages/trackbacks.

Si on cumule tous ces filtres, on atteint finalement un niveau de protection respectable, qui permet de passer au travers des vagues de spam même sophistiquées. À titre d'exemple, le simple blocage du POST sur "referer" ou navigateur nul m'a permis d'éviter 100% des tentatives de spam de 209.160.72.10 (183 en 7 jours), alors que des blogs utilisant les "captcha" ont été largement pollués par cette même machine.

Quoi qu'il en soit, une observation attentive des logs de connexion http du site web à protéger offre toujours des informations intéressantes sur le mode opératoire des spammers, ainsi que des éléments pour affiner la configuration et la protection du site.

One comment

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.