Spam w formularzach (zabaw ciąg dalszy)

Po kolejnych, prawie czterech miesiącach, zabaw w kotka i myszkę ze spam-botami uzupełniam poprzedni post o kilka nowych pomysłów na radzenie sobie ze spamem w formularzach na stronach www.

Uzupełnienie metody II – Ukryte pole

Zamiast tak jak opisano poprzednio:

<input type="hidden" name="metoda2" value="1" />

do formularza wstawiamy ukryte pole bez atrybutu value:

<input type="hidden" name="metoda2" />

Przeglądarki umieszczą zmienną metoda2 w tablicy $_POST jako string(0). Jej wartość także możemy sprawdzić:

<?php
if( !isset( $_POST['metoda2'] ) || $_POST['metoda2'] !== '' ) exit();
?>

Co nam taka zmiana daje? Prawdę mówiąc, jeżeli już bot spamujący prześle zmienną metoda2, to w promilach można liczyć te, które nie prześlą jej wartości jako pusty string. Ale zauważyłem inną ciekawostkę, od czasu usunięcia atrybutu value dość spora ilość botów gubi się (bardziej trafne określenie: psuje się ;-) podczas parsowania formularza. Z logów jasno wynika, że boty nawiązują połączenie z adresem, na który dane mają być przesłane, natomiast tablica $_POST ($_COOKIE, $_GET itd.) jest pusta. Przypuszczam, że brak wspomnianego atrybutu powoduje jakiś syntax error w oprogramowaniu części botów.

Metoda 4 – Kolejność zmiennych w tablicy $_POST

Z analiz logów z ostatniego miesiąca wynika, że to jest najskuteczniejsza metoda ze wszystkich opisanych. Około 80-85% wszystkich wyłapanych spam-komentarzy się na nią nadziewa.

Zasada jej działania jest banalnie prosta. Przeglądarki „układają” kolejne zmienne formularza w tablicy $_POST dokładnie tak jak one w nim występują, większość botów już nie. Jeżeli w WordPress formularz do komentowania wygląda w uproszczeniu tak:

<form action="wp-comments-post.php" method="post">
<p><input type="text" name="author" id="author" size="22" />
<label for="author">Name (required)</label></p>
<p><input type="text" name="email" id="email" size="22" />
<label for="email">Mail (will not be published) (required)</label></p>
<p><input type="text" name="url" id="url" size="22" />
<label for="url">Website</label></p>
<p><textarea class="commbody" name="comment" id="comment" cols="50" rows="10"></textarea></p>
<p><input name="submit" type="submit" id="submit" value="Submit Comment" />
<input type="hidden" name="comment_post_ID" value="ID_postu" />
</p>
</form>

to zmienne w tablicy $_POST ułożą się w następującej kolejności:
author, email, url, comment, submit, comment_post_ID. Jako, że duża część botów się tego nie trzyma (zwykle podają dane w odwrotnej kolejności lub zmienną z treścią komentarza „dają” na samą górę), bardzo łatwo to wykryć, np tak:

$kolejnosc = implode('.', array_keys($_POST));
if( !( strpos($kolejnosc, 'author.email.url.comment.submit.comment_post_ID') === 0 || ( !array_key_exists('author', $_POST) && strpos($kolejnosc, 'comment.submit.comment_post_ID') === 0 ) ) ) exit();

Powyższy przykład będzie działać na wszystkich instalacjach WordPress, czasem (ze względu na zastosowaną skórkę) może być potrzebna zmiana kolejności zmiennych. Uwzględnia także, czy użytkownik jest zalogowany, czy też nie, a także nie kłóci się z polami wstawianym w formularz przez wtyczki.

Zastosowanie a WordPress

Krótki opis jak przedstawione metody zastosować w systemie blogowym WordPress opartym na theme Kubric (w innych podobnie ;-)).

Otwieramy plik szablonu odpowiedzialny za wyświetlanie komentarzy (wp-content\themes\default\comments.php), znajdujemy tag zamykający formularz:

</form>

Tuż przed nim wstawiamy:

<!-- <input type="hidden" name="as_m1" /> -->
<input type="hidden" name="as_m2" />

Czyli końcówka formularza będzie wyglądała tak:
<?php do_action('comment_form', $post->ID); ?>
<!-- <input type="hidden" name="as_m1" /> -->
<input type="hidden" name="as_m2" />
</form>

Następnie w głównym katalogu instalacji WP tworzymy plik antyspam.php z następującą zawartością:

$as_kolejnosc = implode('.', array_keys($_POST));
if( isset( $_POST['as_m1'] ) ) exit();
if( !isset( $_POST['as_m2'] ) || $_POST['as_m2'] !== '' ) exit();
if( !isset( $_POST['submit'] ) || $_POST['submit'] != 'Submit Comment' ) exit();
if( !( strpos($as_kolejnosc, 'author.email.url.comment.submit.comment_post_ID') === 0 || ( !array_key_exists('author', $_POST) && strpos($as_kolejnosc, 'comment.submit.comment_post_ID') === 0 ) ) ) exit();

Jeżeli masz inną nazwę przycisku do wysyłania komentarza niż „Submit Comment”, uwzględnij to w kodzie!

Na koniec dołączamy stworzony plik antyspam.php do znajdującego się w tym samym katalogu pliku wp-comments-post.php. Otwieramy go i na samym początku kodu PHP wstawiamy kod include(‚antyspam.php’);. Czyli początek pliku będzie wyglądał tak:

<?php
include 'antyspam.php';
require( dirname(__FILE__) . '/wp-config.php' );

Pamiętaj o update tego pliku bo aktualizacji WP!

Podsumowanie

Opisane metody razem zebrane, wg moich analiz, wyłapały w ciągu ostatniego miesiąca ponad 97% spamu przychodzącego na mój blog. Ich zalety? Brak potrzeby jakiejkolwiek reakcji ze strony komentującego, całkowicie dla niego transparentne, działające niezależnie od obecności u komentującego graficznej przeglądarki obsługującej JavaScript, szybkie (praktycznie brak obciązenia dla serwera), proste, skuteczne i napewno nie zablokują prawdziwego komentarza. Wady? Spamboty będą coraz doskonalsze, więc skuteczność opisanych metod napewno spadnie.

Kilka ciekawostek

Przytoczona we wcześniejszym poście metoda „czasowa” jest wg moich analiz kompletnie nieskuteczna. W ciągu miesiąca zdarzył się tylko jeden dodany przez bota komentarz w czasie poniżej minuty (dokładnie po 6 sekundach ;)). Po za tym odkryłem pewną ciekawostkę. Pewna grupa botów „keszuje” wyniki parsowania formularzy, rzadko je odświeża i wykorzystuje ponownie! Może by to jakoś wykorzystać do jakiejś kolejnej metody antyspamowej, nie zastanawiałem się jeszcze nad tym.

Mam metodę numer 5, zastosowanie opiszę może w przyszłości. A polega ona na wyłapywaniu linków wstawianych przez znaczną część botów. Wystarczy popatrzeć:

&lt;a href=\&quot;http://adres.do.jakiejs/strony/.htm\&quot; title=\&quot;tytul\&quot;&gt;tekst linku&lt;/a&gt;

Komentujący w ten sposób linków nie wstawia. Uzupełniając tą metodą powyższe osiągnąłem skuteczność ponad 99% w wyłapywaniu spamu!

ps.

Proszę nie pisać w komentarzach o metodach z użyciem JavaScript, Captcha, matematycznych czy innych sprawdzających zdrowie na ciele i umyśle komentujących. Mam świadomość ich istnienia. A tu opisuje, mocno to podkreślam, metody niezależne od używanej przeglądarki przez komentującego, całkowicie dla niego przezroczyste.

Filtry antyspamowe takie jak: Akismet, SpamKarma czy Sblam! także są mi znane, ostatniego nawet używam. Opisane metody mogą dla tych filtrów stanowić uzupełnienie, wstępnie eleminując większość spamu, zostawiając dla nich tylko perelki ;-)


13 Responses to “Spam w formularzach (zabaw ciąg dalszy)”

  • Mendax Says:

    wszystko fajnie, ale co z trackbackami/pingbackami? jakies idee?

  • WaLLacE Says:

    Nie wiem, nie testowałem, nie bawiłem się, nie miałem takiej potrzeby (trackback wyłączony, przez pingback w ciągu roku wpadł jeden spam), a to potrzeba matką wynalazków ;-). Dlatego post jest tylko o spamie wpadających przez formularze.
    A o łapaniu spamu przez trackback/pingback może w przyszłości, gdy będę podpinał je pod wtyczkę obsługującą Sblama.

  • regdos Says:

    przetestowałem powyższe metody na mojej stronie i niestety ich skuteczność nie jest aż taka wysoka jak się spodziewałem, ilosc spamu zmalała ale tylko zmalała.
    A jak by np. dołoży jakieś pole formularza na ukrytego DIV-a albo z display:none ?

  • WaLLacE Says:

    Muszę się zgodzić, luty/marzec na ok. 1500 wiadomości ze spamem przeszło 15, to ten tydzień już przeszło 64. Więc skuteczność spadła, zastanawiam się tylko, czy to zwiększyła się ilość odwiedzających mnie tych „lepszych” botów czy może zaczęli robić lepsze ;-) Wygląda na to, że ta pierwsza opcja jest bardziej prawdopodobna.

    Jeżeli patrzeć z punktu użyteczności, ukryty formularz nie jest dobrym pomysłem, tym bardziej, że także nie na 100% skuteczny.

    Najlepszym sposobem obecnie jest chyba użycia jakiegoś filtru antyspamowego. U mnie Sblam od kilku miesięcy działa bezbłędnie (czego nie wyłapią opisane proste metody, łapie właśnie on).

  • WaLLacE Says:

    A to jednak pomyłka była, po aktualizacji WP zapomniałem podpiąć swoich metod ;-) Po podpięciu dalej wyłapują praktycznie 100% spamu, a filtr antyspamowy ma urlop ;)

  • januzi Says:

    swietna metoda, wczesniej uzywalem rozwiazania z selectem do wybrania opcji „nie jestem spambotem” oraz z radiobuttonami, ale to blokowalo jedynie 40-50% spambotow
    w tej chwili skutecznosc jest 100% :)

  • WaLLacE Says:

    Niestety w przyszłości pewnie spadnie ;)

  • januzi Says:

    do tego czasu moze sie pojawi bezpieczny windows ?
    jak na razie pojawil sie jeden sprytniejszy spambot
    no nic, poczekam z tydzien/dwa i porownam statystyki od sblam!; przed dodaniem tych pol pokazywalo okolo 1800

  • WaLLacE Says:

    W ciągu 57 dni te metody zatrzymały 4657 sztuk spamu (na 4655 z nich wystarczyły metody I i IV, pozostałe 2 złapała II), przeszło 8 sztuk, które zatrzymał Sblam ;)

  • Żółw Says:

    Sposoby ciekawe. Moja strona nie jest jeszcze aż tak popularna żeby odwiedzały je spamboty. Poza tym sam zrobiłem księgę gości więc może po prostu nie widzą jej. Ale system antyspamowy zawsze się przyda, więc zapewne niebawem się w takowy zaopatrzę, a muszę przyznać że przedstawione tu rozwiązania są ciekawe :)

  • WaLLacE Says:

    Boty znajdą Cię niezależnie od popularności ;)

  • sylwia Says:

    Ja tez niestety ciagle walcze ze spamem!

  • RaV Says:

    Cześć WaLLacE, moją księgę gości opanowały spamboty. Próbowałem wpiąć Twoje metody w kod mojej księgi, ale nie działają. Najprawdopodobniej nie potrafię tego zrobić poprawnie. Przyznaję, że nie znam się na tym a wiele zwrotów używanych w powyższej wymianie zdań to dla mnie nowomowa. Czy jest szansa, że mógłbyś mi pomóc? Byłbym niezmiernie wdzięczny gdyż wspomniane boty to diabelskie cholerstwo. Ewentualną odpowiedź proszę przesłać na podany adres e-mailowy. Pozdrawiam, RaV.