Pamiętam, jak zaledwie w kilka godzin po wprowadzeniu na swojej stronie www możliwości pozostawiania komentarzy, zaczęły pojawiać się pierwsze wpisy o możliwości zakupu viagry, xanaxu, przedłużenia pewnych części ciała (nosa, hehe), wraz z adresami www. Oczywiście nie trudno było się zorientować, że wpisy te umieszczane są nie przez żywych ludzi, a przez spamerskie automaty. Prawdopodobnie moja strona www trafiła gdzieś na listę spamerów, którzy zorientowali się o nie zabezpieczonym formularzu www i zaczęli wymieniać tą jakże cenną informacją i po kilku dniach ilość fake'owych komentarzy wzrosła do kilkuset w ciągu dnia. Oczywiście zapanowanie nad tym w sposób ręczny nie było możliwe a poza tym takie rozwiązanie było niezgodne z moją ideologią profesjonalizmu.
Moje poszukiwania w sieci nie trwały długo i na podstawie kilku artykułów stworzyłem własny kod PHP generujący captcha'owe zabezpieczenie do wszelkiego rodzaju formularzy.
Od strony użytkownika (pisze o tym tylko dla formalności) akcja polega na przepisaniu z obrazka do okienka formularza pewnej zdefiniowanej ilości znaków, co dla spamerskich automatów jest praktycznie niemożliwe. Praktycznie, bo jeszcze pewien czas temu np. starsze wersje forum PHPBB generowały proste do zoceerowania (OCR) czcionki, co przy ogromnej popularności tego systemu forów dawało spamerom opłacalność napisania programów rozpoznających tekst i spamujących te fora. Nie sprawdzałem tematu, ale podejrzewam, że współczesne PHPBB jest zabezpieczone na pewno lepiej.
Jeśli ktokolwiek będzie chciał skorzystać z mojego kodu, nie wydaje mi się, aby sensowne było generowanie szczególnie wymyślnych czcionek zlewających się prawie w jeden kolor z tłem. Po pierwsze, bo spamer musiałby napisać program specjalnie pod Twoją stronę www, dostosować nazwy zmiennych pól formularza, co wydaje się nierealne, a zastosowanie bardzo podobnego koloru dla czcionki i tła, co w teorii ma zabezpieczyć przez rozpoznaniem przez automat, zmęczy jedynie oko użytkownika i spowoduje jego zdenerwowanie, a dla automatu odfiltrowanie koloru tła nie jest trudne. Tendencje są obecnie ukierunkowywane raczej w dostawianie literom różnych "wąsów" aby zmylić automaty OCR oraz w generowanie różnych czcionek, jednak tego typu zabiegi raczej zalecane są dla dużych systemów, których złamanie jest dla spamerów opłacalne. Generowanie na mojej stronie czcionki nie są szczególnie proste, ale także nie w żaden sposób wymyślne i jak do tej pory nie przepuszczony został żaden spam. Jednak zawdzięczam to jak sądzę tylko i wyłącznie indywidualnemu charakterowi mojej strony, gdyby kod jej był używany przez dziesiątki tysięcy witryn, być może należałoby zwiększyć trudność złamania kodu obrazka, bo popularność danego systemu niesie za sobą zwiększoną chęć spamerskiej braci na jego złamanie. Oczywiście mój system, jak i inne masowo istniejące w sieci są elastyczne i łatwo można to zmodyfikować choćby poprzez dodanie bardziej wymyślnej czcionki.
Ale zacznijmy od początku. Aby wdrożyć taki system u siebie, należy dysponować podstawowymi umiejętnościami nawet nie programistycznymi, a umiejętnością lekkiej modyfikacji i zrozumienia kodu PHP.
Serwer www musi dysponować PHP i MySQL'em. Należy w bazie danych stworzyć nową tabelę z dwoma kolumnami. Jeśli nie chcesz modyfikować mojego kodu, stwórz tabelę o dowolnej nazwie o kolumnach hash (typu varchar, limit wielkości 32) oraz code (także typu varchar i limicie wielkości 6).
Teraz należy stworzyć skrypt napełniający tą tabelę. Możesz nazwać go napelnij.php:
napelnij.php
<?
$chars = array(2,3,4,5,6,7,8,9,
'a','b','c','d','e','f','g','h','i','j','k','m','n','o','p','q','r','s','t','u','w','x','y','z',
'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','W','X','Y','Z');
$c = mysql_connect("serwer", "user", "haslo") or die (mysql_error());
mysql_select_db("baza", $c);
for($i=0; $i<1000; $i++)
{
$code = "";
for($j=0; $j<6; $j++)
{
$code.=$chars[rand(0, count($chars)-1)];
}
$add = "INSERT INTO nazwatabeli (hash, code) VALUES ('" . md5($code) . "', '" . $code . "')";
mysql_query($add);
};
?>
Krótkie omówienie powyższego kodu:
$chars i znaki w nawiasie - to co znajduje się w nawiasie, będzie wyświetlało się w generowanych obrazkach. Jeśli nie chcesz uprzykrzać użytkownikom życia, możesz usunąć wszystkie wielkie litery i np. cyfry i pozostawić jedynie małe litery. Zapewne zwróciłeś uwagę, że nie występują znaki takie jak 1 (jeden) czy małe L, duże i, łatwe do pomylenia między sobą. Z tych samych powodów nie warto umieszczać zera 0 i litery dużej o (zobacz: 1, I, l, 0, O).
Następnie w zmiennej $c znajdują się wszystkie dane potrzebne do połączenia z bazą danych (serwer, user, haslo, baza). Zmień je wg. własnych potrzeb.
Pętla for $i definiuje, ile różnych rodzajów obrazków ma być generowanych, $i<1000 oznacza, że mój skrypt wygeneruje w bazie tysiąc różnych wpisów. Większa ilość nie wydaje się mieć sensu, jednakże jeśli chcesz, możesz tą liczbę zmienić.
$code=""; czyści zmienną $code po poprzedniej iteracji i wewnątrz pętli $i wykonuje się pętla $j (u mnie sześć razy -> $j<6). Ilość wykonanej pętli $j jest równoznaczna z ilością znaków do przepisania, więc jeśli sześć znaków nie odpowiada Ci, zmień szóstkę w $j<6 na inną liczbę.
$code.=$chars[rand(0, count($chars)-1]; - ta linijka odpowiada za losowe napełnianie sześć razy (u mnie) zmiennej $code znakami z tablicy $chars[]. Znaki te pobierane są w zakresie od pierwszego (0) do ostatniego (count($chars)-1).
$add [...] napełni tabelę bazy danych zaszyfrowanymi przez md5 sumami kontrolnymi kodów w kolumnie o nazwie 'hash', oraz odpowiadającymi im kodami w postaci nie zaszyfrowanej w kolumnie 'code'. Nie zapomnij zmienić 'nazwatabeli' na faktyczną wymyśloną przez Ciebie.
Uruchom teraz swoją przeglądarkę i wpisz w adresie url adres wywołujący stworzony przed chwilą skrypt napelnij.php (czyli coś na podobieństwo http://www.twojastrona.pl/napelnij.php).
Bezbłędne wykonanie skryptu oznaczać będzie ukazanie się czystej pustej strony www. Teraz możesz plik napelnij.php usunać lub zarchiwizować gdzieś w bezpiecznym miejscu. Sprawdź np. poprzez phpmyadmina czy Twoja baza danych faktycznie napełniła się (tu) tysiącem rekordów o sześcioznakowej losowej długości pól code.
Jeśli wszystko jest OK, pora na stworzenie kolejnego pliku, który u mnie nazywa się image.php:
image.php
<?
mysql_connect("serwer", "user", "haslo") or die ("Can not connect to the datebase");
mysql_select_db("baza") or die ("Can not choose datebase " . mysql_error());
$result_captcha = mysql_query("SELECT * FROM nazwatabeli WHERE hash = '$_GET[hash]'") or die (mysql_error());
$get_captcha = mysql_fetch_array($result_captcha) or die (mysql_error());
$image = imagecreatefrompng('red.png');
$red = imagecolorallocate($image, 70, 0, 0);
$black = imagecolorallocate($image, 0, 0, 0);
imagettftext($image, 45, 15, 15, 110, $red, 'harrington.ttf', $get_captcha[code]);
imagettftext($image, 10, 0, 140, 115, $black, 'arial.ttf', 'www.rozenek.com');
header('content-type: image/gif');
imagepng($image);
imagedestroy($image);
?>
Oczywiście tak jak i poprzednio, musisz zmienić w połączeniu do mysql "serwer", "user" i "haslo" oraz "baza", a także "nazwatabeli" w select'ie.
Cóż robi ten plik? Generuje obrazek typu gif. Jak? Strona www (o tym później!!!) na której wyświetla się obrazek do przepisania przesyła do właśnie tworzonego pliku *losowy* hash (czyli zaszyfrowaną wartość kodu) w zmiennej hash. Po połączeniu do bazy danych zostanie pobrana wartość code w postaci niezaszyfrowanej z wiersza o wartości przesłanej w zmiennej hash:
"SELECT * FROM www_captcha WHERE hash = '$_GET[hash]'"
$image = imagecreatefrompng('red.png'); - ta linijka odpowiada za utworzenie tła dla generowanego obrazka. Mój obrazek jest do pobrania tutaj. Będą Ci także potrzebne czcionki: harrington.ttf to generowania samego kodu oraz arial.ttf do generowania opcjonalnego napisu - o czym za chwilę. Pobierz sobie wszystkie trzy pliki.
$red = imagecolorallocate($image, 70, 0, 0);
$black = imagecolorallocate($image, 0, 0, 0);
Powyższe dwie linijki odpowiadają za kolor czcionki. Zmienne nazwałem red i black, jeśli używać będziesz innych kolorów, możesz zmienić ich nazwy, nie zapomnij zmienić ich także w kolejnych liniach kodu! Oczywiście sama zmiana nazw zmiennych nie pomoże w zmianie koloru, za zmianę koloru tak naprawdę odpowiadają cyfry w nawiasach. W moim przypadku dla zmiennej $red w nawiasie $image oznacza, gdzie będą wstawiane literki, czyli do zdefiniowanego wcześniej pliku red.png, 70,0,0 nie oznacza nic innego, jak paletę kolorów RGB. Jeśli nie wiesz co to oznacza, zostaw te wartości jakie są lub poszukaj w sieci. 0,0,0 daje kolor oczywiście czarny.
imagettftext($image, 45, 15, 15, 110, $red, 'harrington.ttf', $get_captcha[code]);
imagettftext($image, 10, 0, 140, 115, $black, 'arial.ttf', 'www.rozenek.com');
Te dwie linijki także mogą być modyfikowane wg. potrzeby. Omówię pierwszą. Cyfra 45 to wielkość czcionki, 15 to jej pochylenie, 15 i 110 to współrzędne xy gdzie napis ma zacząć się pojawiać, $red zostało omówione przed chwilą, harrington.ttf to nazwa czcionki użytej do generowania napisu a $get_captcha[code]) to sam napis w postaci niezaszyfrowanej, pobrany z bazy danych. W kolejnej linii zamiast niego jest wyświetlany statycznie napis www.rozenek.com. Możesz go oczywiście zastąpić innym napisem lub usunąć linie odpowiedzialne za jego generowanie.
Kolejne linie nie wymagają żadnych zmian, więc nie będę ich omawiał, zainteresowanych odsyłam do dokumentacji.
Teraz pora na kod odpowiedzialny za wyświetlanie grafiki już na właściwej, zabezpieczanej stronie:
Przyjmijmy, że strona z formularzem nazywa się
formularz.php
Tak jak wcześniej pisałem, osoba wykorzystująca ten artykuł do własnych celów musi znać chociaż trochę HTML i PHP. Konkretne zastosowanie kodu w mojej stronie dostępne jest TUTAJ. W tym artykule przestawię tylko najważniejsze linijki kodu pliku formularz.php:
$result_captcha = mysql_query("SELECT hash FROM nazwatabeli ORDER BY RAND() LIMIT 1") or die (mysql_error());
$get_captcha = mysql_fetch_array($result_captcha) or die (mysql_error());
<img width="256" height="120" src="http://www.rozenek.com/captcha/image.php?hash=<?=$get_captcha['hash'] ?>">
<input type = "text" name="code">
<input type="hidden" name="hash" value="<?=$get_captcha['hash'] ?>">
No to pora na omówienie kodu. $result_captcha pobiera z bazy danych z tabeli 'nazwatabeli' losowo wybrane jedno pole hash. Jest to zaszyfrowana postać napisu w obrazku.
<img> wyświetla następnie generowany w pliku image.php obrazek, przekazując mu wartość hash odczytaną losowo z bazy jako parametr.
Użytkownik do pola formularza o nazwie code wpisuje wartość z obrazka, a ukryte pole formularza przekazuje dodatkowo zaszyfrowaną wartość hash.
Wszystko to jest wysyłane do pliku np.
add.php
którego zadaniem jest sprawdzić, czy wpisana wartość z obrazka jest prawidłowa i jeśli tak, opublikować komentarz czy cokolwiek innego co jest zabezpieczane przez captcha'ę.
Logarytm jest następujący:
Jeśli (wprowadzona wartość nie jest prawidłowa)
{
wyświetl "TY SPAMERZE!!!" :-)
}
w przeciwnym wypadku
{
opublikuj komentarz
}
Pora na kod:
$result_captcha = mysql_query("SELECT * FROM www_captcha WHERE hash = '$_POST[hash]'") or die (mysql_error());
$get_captcha = mysql_fetch_array($result_captcha) or die (mysql_error());
if ($get_captcha[code]!=$_POST[code])
{
akcja gdy captcha nieprawidłowa
}
else
{
akcja gdy wszystko OK
}
Mam nadzieję, że powyższy artykuł pomoże zainteresowanym w napisaniu własnego systemu zabezpieczającego przed spamem strony www. Mam nadzieję, że na miarę swoich możliwości byłem w stanie wytłumaczyć zasadę działania kodu.
A teraz ciekawostka. Zobacz ostatnie rekordy przechwycone przez moje logi z prób umieszczenia spamu na mojej stronie. Widzę teraz sam, że częstotliwość prób znacznie się zmniejszyła od momentu wprowadzenia zabezpieczenia, być może url mojej strony został przez spamerów usunięty po wprowadzeniu zabezpieczenia. Tak czy inaczej - proszę uwierzyć, że w momencie powstawania strony, gdy nie było jeszcze systemu CAPTCHA, były to nawet setki wpisów w ciągu doby. A teraz obiecany wycinek logów:
12.09.2010 - z ostatniej chwili: w ciągu kilkunastu miesięcy, już około 5...6 raz pomimo captchy dostałem na swojej stronie spam w komentarzach.
Podejrzewam dwie możliwości: ktoś ręcznie wklepuje zadawane mu do "odszyfrowania" kody (podobno ludzie z biednych krajów dorabiają w ten sposób) lub też, co także jest możliwe - jakiś program OCRujący rozpoznaje moją captchę. Co dziwne - w 99% przypadków spam był pozostawiany właśnie na tej stronie, czyli na stronie mającej za zadanie pomóc w walce ze spamerami - czyżby czyjaś zemsta? :-)
Tak czy inaczej, postanowiłem zadziałac - na TEJ stronie opisywałem swojego czasu system mojej konstrukcji, pozwalający na głosowanie (ocenianie) artykułów. System jest zabezpieczony poprzez podłożenie fakeowych pól formularza, wypełnianych przez roboty - na tym się właśnie one wykładają.
Pomyślałem, że może właśnie będzie to pomocne w walce ze spamem w komentarzach - zaaplikowałem poprawkę dzisiaj - czy pomoże - czas pokaże :-)
Poprawka wygląda następująco: w formularzu komentarzy umieszczamy dwie fake'owe linijki:
<input type="text" name="catcher" value="catcher" style="display: none;">
<input type="text" name="catcher2" value="" style="display: none;">
W pliku odbierającym zgłoszenie formularza dostawiamy dodatkowy warunek:
if (($_POST['catcher']=="catcher")&&($_POST['catcher2']=="")) {nie spamer, dodaj komentarz}
Czemu tak? Liczę na to, że robot będzie wypełniał wszystkie napotkane pola formularza, więc wpadnie na tym. Być może także spróbuje wszystkie je wyczyścić, przez co także zostanie wykryty jako intruz.
Cóż, czas pokaże, czy było pomocne :-)
Tak czy siak - koło dziesięciu spamów przez ponad rok - nie jest źle :)
| Podobalo Ci sie? Chcesz mi jakos podziekowac? Wcisnij "Lubie To":
|
|
|
|