CAPTCHA bez dręczenia użytkownika
CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) – rodzaj techniki stosowanej jako zabezpieczenie na stronach www, celem której jest dopuszczenie do przesłania danych tylko wypełnionych przez człowieka.
Zapewne nie raz spotkaliście się z kodami obrazkowymi które trudno było rozpoznać nawet człowiekowi. Widziałem już różne zabezpieczenia przeciw spam botom, mniej lub bardziej wymyślne, a nawet takie które spowodowały że sobie odpuściłem wysłanie formularza gdyż nie byłem w stanie ich pomyślnie przejść.
W tym wpisie pokaże Wam jak zrobić alternatywne metody weryfikacji człowieczeństwa bez denerwujących kodów obrazkowych czy innych mechanizmów utrudniających życie.
Być może to co opiszę ktoś już wynalazł i stosuje z powodzeniem, nie mniej, wymyśliłem to przy okazji jednego projektu gdzie po dziś dzień działa i spisuje się znakomicie – chyba że tą stronę omijają spam boty
.
Idea
Na czym polega ów metoda? Na dynamicznej zmianie formularza, przed jego wysłaniem. Kolejno, w skrypcie PHP obsługującym daną formę, sprawdzamy poprawność struktury.
Spam boty, przeczesując sieć, odczytują z kodu HTML dostępne pola i wysyłają żądanie POST do lokacji widniejącej w parametrze action. Jeśli zmienimy formularz dynamicznie przy pomocy JavaScript’u, wtedy spam bot nie zobaczy tych zmian i wyśle pierwotną wersję – wyjątkiem było by tutaj gdyby bot działał jak przeglądarka i interpretował całą stronę, ale w to wątpię.
Praktyka
Jeśli powyższy opis nie jest zbyt jasny, to poniższy przykład rozwieje wszelkie wątpliwości.
Załóżmy że mamy prosty formularz z jednym polem tekstowym – na przykład do dodawania komentarzy na stronę.
<form id="form" action="form.php" method="post"> <input type="text" name="comment"> <input type="submit" name="submit" value="Wyślij"> </form>
Po wysłaniu takiej formy i zrzuceniu w PHP zawartości tablicy $_POST otrzymamy:
array(2) {
["comment"]=>
string(14) "mój komentarz"
["submit"]=>
string(7) "Wyślij"
}
I w ten sposób wyglądała by przesłana zawartość jeśli wysłał by ją spam bot. Teraz wprowadzimy kilka zmian, aby ta wysłana przez człowieka (tj. z tradycyjnej przeglądarki) różniła się od tej powyższej.
Skorzystam z biblioteki jQuery w celu łatwiejszego manipulowania elementami dokumentu HTML.
$(document).ready(function(){
$('#form').append('<input type="hidden" name="key" value="234786">');
$('#form input[name="submit"]').removeAttr('name');
});
Co zrobiłem? Tuż po załadowaniu całego dokumentu, dodałem nowe ukryte pole formularza o nazwie key i wartości 234786. Kolejno, usunąłem atrybut name z przycisku submit. Po takim zabiegu, skrypt PHP widzi nasz formularz w następujący sposób:
array(2) {
["comment"]=>
string(14) "mój komentarz"
["key"]=>
string(6) "234786"
}
Jak widać, nie występuje już w tablicy $_POST w ogóle przycisk submit, a dodatkowo doszło ukryte pole key.
Jeśli teraz wyczulimy skrypt przetwarzający formularz na te zmiany, możemy odróżnić bota od człowieka:
if (( ! isset($_POST['submit'])) && isset($_POST['key']) && ($_POST['key'] == '234786'))
{
echo 'jesteś człowiekiem :]';
}
else
{
echo 'jesteś spam botem :[';
}
Zabezpieczenia
Pokazane tutaj rozwiązanie, w postaci usunięcia atrybutu przycisku submit, oraz dodanie pola hidden są tylko przykładowe. Siła tego rozwiązania tkwi w unikalności metody, a tutaj mamy naprawdę spore pole do popisu.
Możemy dodawać i usuwać pola. Manipulować nazwą lub zawartością pól ukrytych, np.: jego wartość musi być sumą kontrolną z tego co wpisze użytkownik w innym polu (wymagane podpięcie się pod zdarzenie onSubmit w takim wypadku). Możemy dodać pole z nazwą przeglądarki, adresem IP i porównać w skrypcie PHP czy się zgadzają oba wpisy. Pole do popisu jest naprawdę ogromne – niech poniesie Was fantazja, grunt to dobrze namieszać
.
Sam kod JavaScript warto umieścić w zewnętrznym pliku oraz potraktować narzędziem typu kompresor JS. To utrudni ew. rozgryzienie naszego przypadku.
Uwagi
Czy jest to rozwiązanie idealne? Oczywiście nie. Pierwsza wada to wymagana obsługa JavaScript u użytkownika. Druga to łatwość obejścia tego typu zabezpieczenia przez człowieka. I tutaj są dwa aspekty tej przypadłości.
Autor bota musiał by przejrzeć kod naszej strony i zorientować się co tam się dokładnie dzieje i zmodyfikować swój twór. Jeśli przyjmiemy że każdy webmaster zastosuje inny algorytm zabezpieczający, to mało komu będzie się chciało dostosowywać swojego szkodnika do każdej strony z osobna tylko po to by móc masowo spamować. Koszt tej operacji przewyższał by zyski z rozsyłanego spamu.
Czyli, zasadniczo da się prosto dojść do tego jak spreparować formularz (chociaż jeśli ktoś namiesza to wcale to takie łatwe być nie musi
), jednak jest to z ekonomicznego punktu widzenia nieopłacalne dla spamera.
dowolny spambot z interpretacją javaskryptu ominie to zabezpieczenie (o ile się jeszcze czegoś nie namiesza po drodze). celem CAPTCHA jest oddzielenie automatu od człowieka a tu mamy cały test robiony przez automat, zwany przeglądarką internetową. Wystarczy raz w przeglądarce wpisać wiadomość, potem kliknąć dodaj komentarz, a potem ustawić auto-odświeżanie i wiadomość doda się tyle razy ile właściciel przeglądarki sobie zażyczy.
takiego generycznego spambota z przeglądarki można zrobić w FF przez greasemonkey; piszemy skrypt który po naczytaniu strony i przetworzeniu js na stronie wklei jakąś treść do ‘comment’ i wywoła ‘submit’a.
No jeśli spambot umie interpretować JS to masz rację, ale to musi być praktycznie przeglądarka. Nie znam się na rozwoju spambotów
jeśli takie stanowią obecnie większość to faktycznie metoda niezbyt udana.
Z drugiej strony, jeśli słyszy się o wynajmowaniu taniej siły roboczej z krajów wschodu do wspomagania botnetów i omijania graficznych captcha to już trudno wymyślić coś co jest skuteczne
Właśnie, trudno jest zrobić dobre CAPTHCHA. Metody oparte o losowe pytania na tak/nie są złe, bo bot ma 50% szans na trafienie, odczytywanie z obrazka jest złe bo często bardziej uciążliwe dla usera niż bota, a stosowanie tricków opartych o założenie że bot różni się od przeglądarki i usera w sposób technologiczny jest o tyle złe że założenie nie musi być spełnione.
Automatyczna filtracja treści/ilości wiadomości też popełnia błędy, a ręczna filtracja jest niewygodna.
Wg. mnie dobre są działania matematyczne. Ogółem proste dla człowieka, i łatwiej je wykonać czasami niż się męczyć z odczytaniem obrazka. Np: dwa dodać osiem
Najlepiej tekstem właśnie.