hCaptcha na WordPress przeciwko spamowi

Jednym z powodów dla których umieściłem CAPTCHA[1] na blogu była chęć zmniejszenia ilości spamu w komentarzach. Dokładniej, ilości spamu do moderacji, bo i tak wszystkie komentarze przechodzą tu przez ręczną moderację, nim pojawią się na blogu.

Na początek drobne statystyki. WordPress pokazuje równe 230 komentarzy oznaczonych jako spam. Najstarszy z 24.10.2018. Do wczoraj[2] daje to 909 dni, czyli średnio ok. jednego spamu na cztery dni. Nie jest to dokładna statystyka, część mogłem kiedyś usunąć, zamiast oznaczyć jako spam. Zjawisko nie było też stałe w czasie. Mam wrażenie, że ostatnio się nasilało. Na pewno luty, marzec i kwiecień tego roku to większe ilości. Z kolei styczeń to tylko pięć spamów. Jeśli miałbym oceniać na oko, to stawiałbym bardziej średnio na spam co drugi dzień. Do przeżycia.

Rodzajów spamu też było kilka i pojawiał się falami. Były i polskie pseudokomentarze typu „ciekawy wpis” z typowym SEO linkiem, i komentarze pisane cyrylicą. Dominowały jednak anglojęzyczne reklamy środków viagropodobnych. Regularności we wpisach pod którymi zamieszczano komentarze praktycznie żadnej. Podobnie z IP wykorzystywanymi do wysyłki spamu. Na oko raczej stare wpisy, z różnych kategorii. 230 to nie jest duża próbka do analizy, ale może kiedyś zrobię statystyki.

W każdym razie w ostatnim czasie liczba spamów wzrosła. Dominował w zasadzie jeden IP: 92.204.174.134, we WHOIS mający powiązania z SEODEDIC. Zamieszczał nawet po trzy komentarze dziennie. Sprawdzenie logów serwera WWW pokazało, że po prostu wchodzi i wysyła komentarz. Żadnych wielokrotnych prób, ale niekoniecznie byłyby widoczne po stronie mojego serwera. Zatem ciężko stwierdzić czy któryś z serwisów do omijania CAPTCHA przy pomocy ludzi, czy sprytne metody typu machine learning do rozpoznawania obrazków[3] czy w końcu może sprytne wykorzystanie Google text to speech do obchodzenia CAPTCHA od Google.

Skoro spamerzy obchodzili reCAPTCHA, stwierdziłem, że to dobra okazja do wypróbowania alternatywy, o której ostatnio trochę było słychać. Chodzi o serwis hCaptcha. Rejestracja niezbyt gładka. A to mail na Onecie został uznany za nieprawdziwy adres email, a to były problemy z dostarczeniem maila z linkiem aktywacyjnym na inną skrzynkę. W końcu odnalazł się on w folderze spam.

Po aktywacji jest już z górki. Użyłem pluginu hCaptcha for WordPress, który pozwala na określenie, gdzie ma być serwowana CAPTCHA. Podajemy klucze API i… już. Przyznam, że kusiło mnie przez moment wypróbowanie używania obu pluginów jednocześnie. Szybko porzuciłem tę myśl. CAPTCHA jednak i jest nieco upierdliwym mechanizmem, i dokłada trochę objętości do wielkości strony.

No właśnie. W porównaniu z pierwotną wersją strona jest obecnie nieco cięższa. I główna, i strony poszczególnych wpisów. Dramatu nie ma, nad główną jeszcze popracuję, ale z kronikarskiego obowiązku odnotowuję.

Co dalej? Ano czekam na feedback od użytkowników jak się nowa CAPTCHA podoba. A jeśli spamer wróci z tego samego IP, to dostanie w łeb. Tarpitem. Jeśli i to nie pomoże, poszukam innych pluginów WordPress stworzonych, by zwalczać spam. No i przede wszystkim będę obserwował ilość spamu przychodzącego do moderacji.

[1] Dokładnie reCAPTCHA wraz z pluginem Advanced noCaptcha & invisible Captcha. Tutaj znajdziesz więcej o wykorzystywanych na tym blogu czy polecanych pluginach do WordPressa.
[2] Jeśli ktoś zada sobie trud policzenia, to wyjdzie nieścisłość matematyczna. I można policzyć ile dni wpis leżakował jako szkic.
[3] Tak, to akurat przeciwko hCaptcha, ale miałem pod ręką linka. Dla reCaptcha pewnie też coś analogicznego istnieje.

Poznański Budżet Obywatelski i CAPTCHA

Jak co roku można było głosować na Poznański Budżet Obywatelski. Wszedłem na stronę, zobaczyłem CAPTCHA i… zaniemówiłem. Implementacja, którą zobaczyłem była prostsza do połamania (czyt.: rozwiązania automatem) niż opisywana kiedyś CAPTCHA Agory. Polegała na podaniu wyniku dodawania dwóch liczb, podanych słownie, z zakresu 1-10. Dla ułatwienia tekst był podawany jawnie, jako tekst w HTML.

Jak już podniosłem szczękę z podłogi i przetarłem oczy, to dziesięć minut później miałem skrypt, który bezbłędnie podawał wynik. Zgłosiłem podatność, wraz z sugestią, żeby skorzystać z gotowców, a nie własnej, wadliwej implementacji CAPTCHA. Szybko otrzymałem odpowiedź, którą można streścić… it’s not a bug, it’s a feature:

Obecnie funkcjonujący mechanizm CAPTCHY został wprowadzony nie tylko w oparciu o bezpieczeństwo, ale również przystępność użytkowania, co w przypadku tak różnorodnej grupy osób jak grupa głosujących w Poznańskim Budżecie Obywatelskim, jest szczególnie ważne.

[…]

Zaproponowane przez Pana rozwiązanie – skorzystanie z usług zewnętrznych takich jak Google – jest niemożliwe do wprowadzenia, ponieważ musimy opierać się na własnych, niezależnych od firm zewnętrznych rozwiązaniach, co zapewnia nam pełną możliwość ingerowania w przypadku wystąpienia ewentualnych błędów czy problemów z usługą.

Wyciąłem opis dodatkowych mechanizmów weryfikacji osób głosujących, które na szczęście są obecne. Jednak stawka, o którą toczy się gra jest wysoka – nawet 2 mln za projekt ogólnomiejski. Liczę więc, że w przyszłym roku zabezpieczenia będą lepsze. Rozważyłbym wręcz wykorzystanie Profilu Zaufanego, tak po prostu. W tym roku wygenerowanie dodatkowych głosów było dość proste, choć sam automat do łamania CAPTCHA nie wystarczyłby.

Tak w ogóle nie zagłosowałem w tym roku – pamiętałem, żeby czekać do końca października i… przypomniałem sobie o głosowaniu 31.10. Skończyło się dzień wcześniej. Mówi się trudno.

UPDATE Niewielka aktualizacja w celu doprecyzowania w czym rzecz wynikająca z rozmowy. CAPTCHA, której rozwiązanie jest możliwe automatycznie to… nie CAPTCHA. Spokojnie można ją pominąć. Gdyby ktoś miał złe intencje i dostęp do bazy danych z danymi paru tysięcy mieszkańców Poznania, to stosunkowo łatwo, automatycznie mógłby w tym roku zmienić wyniki głosowania. Przy czym problem jest głębszy i CAPTCHA w Poznańskim Budżecie Obywatelskim, nawet działająca, nie ratuje tu sytuacji. Skala kilku tysięcy głosów jest do obsłużenia ręcznie, nawet przez pojedynczą osobę.

Profil Zaufany jest podobno mało popularny, nie mam zatem pomysłu jak sensownie zabezpieczyć tego typu głosowanie przez internet.

Spam na Blox, czyli jak nie implementować CAPTCHA.

Od dłuższego czasu serwis blogowy Blox boryka się z plagą spamu. Słyszałem zapewnienia, że moderatorzy/admini walczą z tym zjawiskiem, ale wydaje mi się, że bez większych sukcesów, a nawet, że problem spamu się nasila. Jest to zjawisko dla wszystkich (poza spamerami) niekorzystne, a nierzadko na stronie głównej o pewnych porach spamy stanowią 30 i więcej procent wpisów.

Postanowiłem zerknąć na proces zakładania konta od początku. Pierwsze co rzuciło mi się w oczy, to prostota CAPTCHA. Być może parę lat temu wystarczało coś takiego, by odstraszyć spamerów, ale wojna trwa – istnieją narzędzia do automatycznego rozpoznawania nawet dość skomplikowanych CAPTCHA ze stosunkowo dużą pewnością (grubo ponad 50%). Niedawno nawet Jogger, który pozwalał właścicielowi bloga na mocne zmiany wyglądu CAPTCHA (kształt, wielkość, kolor), przy komentarzach dorzucił do niej litery obok cyfr, bo spamerzy się przebijali…

Żeby sprawdzić, czy nie przypadek, że CAPTCHA jest taka słaba, wcisnąłem F5, raz, drugi, trzeci… I okazało się, że trafiłem na powtarzające się słowa. Chwilę się pobawiłem i faktycznie, nie da się ukryć, CAPTCHA powtarza się i to – na oko – często. Postanowiłem sprawę zbadać dokładniej.

Sposób badania: uruchomienie przeglądarki, wyczyszczenie historii, w każdej serii 50 przeładowań strony (F5 lub ctrl-r), zapisanie wyników do pliku (każdy wynik w pojedynczej linii) w takiej kolejności, w jakiej się pojawiały. Żeby wykluczyć wpływ User Agent i czasu, każda seria wykonywana na różnej przeglądarce i w odstępie minimum kilkudziesięciu minut.

W pierwszej serii (przeglądarka chromium) 50 ciągów wyrazów wystąpiły 32 unikatowe ciągi, przy czym 4 wystąpiły trzykrotnie, 10 dwukrotnie, a 18 tylko raz. Dodatkowo rzuciła mi się w oczy prawdopodobna metoda powstawania wielu CAPTCHA – podział słowa na sylaby, połączone z ew. wyrzuceniem niektórych liter, a następnie wymieszanie tych slab. Przykładowo zykamu i kazymu (czyli muzyka), letefon, fontele i fonlete (czyli telefon), zetagagataze (czyli gazeta), lafiorka, fiorkala, fiorlaka (czyli kalafior).

Druga seria, kilkadziesiąt minut później na midori – 34 unikatowe ciągi, jeden wystąpił czterokrotnie, 13 dwukrotnie, 20 jednokrotnie. Wyrazy zdecydowanie powtarzają się między seriami – dla obu serii łącznie wystąpiło 46 unikatowych ciągów, 2 wystąpiły pięciokrotnie, 6 – czterokrotnie, 8 – trzykrotnie, 12 -dwukrotnie, 18 – jednokrotnie.

Ponieważ ciąg znaków pod którym można poprać losowany obrazek może być stały (z danego można korzystać wiele razy), postanowiłem uprościć sobie pobieranie i przeliczanie. Szybki skrypt, który przy pomocy wget pobiera zadaną ilość obrazków i zapisuje do kolejnych plików, a następnie sprawdzenie sum kontrolnych (md5) tychże plików. I tu ciekawostka – sumy kontrolne praktycznie się nie powtarzają. Sprawdziłem organoleptycznie i faktycznie – o ile wyrazy powtarzają się często, to praktycznie każdy plik jest binarnie inny. Czyli raczej mała ilość wyrazów raczej nie wynika z chęci cache’owania.

Dla porządku: dla 100 plików 3 miały takie same sumy kontrolne, a kolejne 5 sum występowało dwa razy. Powtórzyłem eksperyment dla 1000 plików. Pojawiło się 611 unikatowych sum kontrolnych, jedna z sum występowała 7 razy, jedna 6, sześć wystąpiło 5 razy, cztery – 20 razy, trzy – 53 razy, dwie – 188 razy i jedna – 342 razy.

Nie sprawdzałem dokładnie, czy dany wyraz w CAPTCHA koreluje z ciągiem w treści (na oko nie), ani z jaką skutecznością zadziała automatyczne rozpoznawanie, ale przy tak częstym powtarzaniu się ciągów znaków i plików nie ma to znaczenia – wygląda, że baza jest za mała, a przekształcenie zbyt proste i można spokojnie stworzyć skrypt, który porówna sumę md5 wygenerowanego pliku z arbitralną bazą.

O problemie pisałem wstępnie na forum, póki co bez odzewu. W każdym razie liczę na to, że wpis zmotywuje administratorów blox do załatania ewidentnej dziury w zakładaniu nowych kont. Obecne likwidowanie spamerskich blogów przypomina wylewanie wody z łódki, zamiast załatania w niej dziury, przez którą wody nabiera.

Oczywiście najlepsze byłoby podpięcie jakiegoś znanej, sprawdzonej implementacji CAPTCHA, zamiast wymyślania koła od nowa (i to sugestia dla tych, którzy chcą stosować tego typu rozwiązanie) ale wydaje się, że nawet z istniejącą implementacją można prosto zadziałać w taki sposób, że stanie się ona choć w części efektywna. Przede wszystkim mam na myśli zwiększenie bazy słów i ilości przekształceń.

Obok złych wiadomości są też i dobre – co prawda problem nie jest to Blox, tylko ogólnie dotyczy konto.gazeta.pl, ale – jak wynika z korespondencji z administratorami Blox – jest znany i ma być najdalej w kwietniu poprawiony. Pozostaje uzbroić się w odrobinę cierpliwości i liczyć na to, że po załataniu dziury uda się skutecznie pozbyć spamerów. W tej chwili bywa tak, że 100% wpisów na głównej stanowią spamy…