Skrypt CAPTCHA

Ostatania modyfikacja: 28 września 2017, kategoria: Php

CAPTCHA to technika stosowana w skryptach, umożliwiająca wprowadzanie danych do formularzy tylko przez ludzi, odrzucając roboty sieciowe. Używanie CAPTCHY (potocznie kapeć) w dzisiejszych czasach jest koniecznością. Wszelkiego rodzaju skrypty i programy spamujące stały się plagą i nieodłączoną częścią internetu. Każdy niezabezpieczona strona widniejąca w wyszukiwarce google zostanie wcześniej czy później zasypana komentarzami oraz postami.

Czym jest skrypt CAPTCHA

CAPTCHA spotykana jest w wielu formularzach wymagających podawania danych przez użytkowników. Wyświetlana jest w postaci obrazka lub działania matematycznego, treść obrazka lub wynik działania należy przepisać w odpowiednie pole. Dzięki temu robot sieciowy nie może zarejestrować nowego konta lub dodać setek komentarzy w ciągu paru sekund.

Skrypty CAPTCHA są stale rozwijane i udoskonalane. Przyczyną tego są skrypty potrafiące łamać captchę, tzn. potrafiące odczytywać tekst z obrazka lub potrafiące obliczać działania matematyczne wyświetlone na stronie. Zaawansowane skrypty CAPTCHA mają nieczytelne litery, różne kolory, wszelkiego rodzaju kreski i losowe położenie cyfr i liter. Wszystko po to aby utrudnić odczyt CAPTCHY robotom.

CAPTCHA obrazkowa

Jest to najskuteczniejszy rodzaj CAPTCHY spotykany na popularnych serwisach. Wymagane jest stworzenie skryptu PHP generującego losowy obrazek. Obrazek wyświetlamy w formularzu. Oprócz generowania obrazku skrypt musi zapisać treść z obrazka do zmiennej sesyjnej (np. $_SESSION[‚captcha’];).

Kod pliku captcha.php

<?php
session_start();
$znaki = '0123456789';		// dozwolone znaki
$szerokosc = 170; 		// szerokość obrazka
$wysokosc = 30;			// wysokość obrazka
$ilosc_znakow = 6;		// długość captchy
$str = '';			// zmienna pomocnicza

// losowanie ciągu znkaów
for ($i = 0; $i < $ilosc_znakow; $i++)
	$str .= substr($znaki, mt_rand(0, strlen($znaki) -1), 1);

$string = $str;
$_SESSION['captcha'] = $string; // przypisanie do zmiennej sesyjnej

// tworzenie obrazka o danych wymiarach
$im = imagecreate($szerokosc, $wysokosc);

//kolory obrazka
$tlo	 = imagecolorallocate($im,0,0,0);
$czcionka   = imagecolorallocate($im,255,255,255);
$siatka   = imagecolorallocate($im,78,78,78);
$ramka = imagecolorallocate ($im, 255, 0, 0);

imagefill($im,1,1,$tlo); // wypełnienie tłem

// losowanie siatki
for($i=0; $i<1600; $i++)
{
	$rand1 = rand(0,$szerokosc);
	$rand2 = rand(0,$wysokosc);
	imageline($im, $rand1, $rand2, $rand1, $rand2, $siatka);
}

// losowanie pozycji znaków
$x = rand(5, $szerokosc/(7/2));

// dodawanie obramowania
imagerectangle($im, 0, 0, $szerokosc-1, $wysokosc-1, $ramka);

// umieszczanie liter na obrazku
for($a=0; $a < 7; $a++)
{
	imagestring($im, 6, $x, rand(4 , $wysokosc/5), substr($string, $a, 1), $czcionka);
	$x += (5*3); // odstęp między literami
}

// zwrócenie wygenerowanego obrazka, ustawienie typu mime na GIF
header("Content-type: image/gif");
imagegif($im);
imagedestroy($im);
?>

Możesz zmienić wymiary i kolory generowanego obrazka. Plik captcha.php wyświetlamy teraz w formularzu tak jak każdy inny obrazek. Obok należy umieścić pole tekstowe na wpisanie treści z obrazka. Aby sprawdzić czy wpisany kod CAPTCHA jest poprawny, pobieramy metodą POST wartość wpisaną w polu tekstowym i porównujemy ze zmienną sesyjną o nazwie captcha.

Sprawdzanie poprawności captchy

<?php
if ($_POST['kod']==$_SESSION['captcha'])
{
	echo "Wpisałeś poprawny kod.";
	//reszta skryptu
}
else
{
	echo "Wpisany kod jest niepoprawny.";
}
?>

CAPTCHA tekstowa.

Skuteczność tego rozwiązania jest mniejsza, jednak bardzo dobrze sprawdza się to na małych stronach. Mniejsza skuteczność spowodowana jest łatwością napisania skryptu wykonującego podane przez nas działanie matematyczne. Jednak aby taka sytuacja zaistniała, ktoś musiał by napisać skrypt specjalnie pod naszą stronę, wycinający działanie matematyczne za pomocą wyrażeń regularnych.

Działanie jest identyczne jak w przykładzie graficznym. Zamiast generować obrazek, wystarczy wygenerować kilka cyfr za pomocą funkcji rand. Wynik zapisujemy do zmiennej sesyjnej, a działanie wyświetlamy w formularzu.

Podsumowanie

Z mojego doświadczenia wynika, że wystarczy nawet proste „Wpisz wyraz KOT w polu obok” aby zablokować 99% robotów sieciowych i nie potrzeba do tego żadnej CAPTCHY. Jednak lepiej dmuchać na zimne niż któregoś dnia obudzić się z 10MB spamu w bazie danych.

Użytkownik charli napisał:

13 kwietnia 2013


bardzo fajny skrypcik pozdrawiam

Użytkownik Jon napisał:

15 sierpnia 2013


Dobrze i prosto to przedstawiasz i tak rób dalej.

Użytkownik arek napisał:

22 sierpnia 2013


A jak dopisać te pole tekstowe ?
pozdrawiam

Użytkownik Karol napisał:

22 sierpnia 2013


Jakoś tak:

< form name="captcha" method="post">
< img src="captcha.php" alt="captcha">
< input name="kod" type="text" value="przepis obrazek">
< input name="sbm" type="submit" value=" OK ">
< /form>

Użytkownik sz napisał:

03 kwietnia 2014


dzięki, kod się przydał :-)

Użytkownik Maciek napisał:

23 kwietnia 2014


„Mniejsza skuteczność spowodowana jest łatwością napisania skryptu wykonującego podane przez nas działanie matematyczne. Jednak aby taka sytuacja zaistniała, ktoś musiał by napisać skrypt specjalnie pod naszą stronę, wycinający działanie matematyczne za pomocą wyrażeń regularnych.”

Mógłbyś przybliżyć jak coś takiego zrobić? W czym taki skrypt napisać itd. Oczywiście w celach edukacyjnych ;)

Użytkownik Karol napisał:

23 kwietnia 2014


Program pobierający źródło strony możesz napisać praktycznie w każdym języku, także PHP umożliwia taką funkcję. W PHP osiągniesz efekt używając biblioteki cURL lub funkcji PHP o nazwie „file_get_contents”.

Kiedy masz źródło strony to wydobycie dowolnego ciągu znaków nie sprawia żadnych trudności. Wystarczy proste wyrażenie regularne, które dopasuje odpowiedni wzorzec.

cURL udostępnia także funkcję wysyłania (i wypełniania) formularzy HTML. Także jeżeli masz adres strony, odczytasz captchę, to możesz bez problemu zaspamować komuś komentarze, fikcyjne konta lub różne inne rzeczy wysyłane drogą zapytań POST.

Użytkownik Maciek napisał:

27 kwietnia 2014


Dzięki, o taką odpowiedz mi właśnie chodziło.

Użytkownik es napisał:

03 listopada 2014


witaj,
mam pytanie /ponoć kto pyta nie błądzi../ :
w którym miejscu w pętli ‚losowanie siatki’ /wiersz 28/, wykorzystywana jest zmienna $i ?

pozdrowienia

Użytkownik Karol napisał:

03 listopada 2014


Cześć. Iterator pętli nie jest wykorzystywany jak dobrze zauważyłeś. Operacje wewnątrz pętli należało powtórzyć wiele razy aby uzyskac losowy wygląd obrazka, jednak wykorzystanie zmiennej $i nie jest potrzebne

Użytkownik es napisał:

03 listopada 2014


dzięki za wyjaśnienie,
pozdrowienia

Użytkownik Kazimiera napisał:

10 września 2017


Widzę, że wpis jest z 2014r., ale mam problem i może otrzymam od Ciebie pomoc. Mam problem z Captchą obrazkową przez co nie mogę korzystać z wielu stron, na których mi zależy. Obrazki Captcha pojawiają się, ale po naciśnięciu wybranego obrazka znika on, a nie zostaje odznaczony. Nawet jak dobrze uda mi się za którymś razem zaznaczyć właściwe obrazki i zostaję to potwierdzone zielonym znaczkiem to i tak pojawia się napis: „Incorrect captcha solution – please try again „. Nie wiem co mam robić.

Użytkownik Artur K. napisał:

25 marca 2019


Skrypcik fajny, bo prosty i dzięki temu łatwy do zrozumienia i dostosowania do własnych potrzeb.
Warto jednak zauważyć, że w obecnej formie jest on podatny na ataki m.in.:

1) CAPTCHA reuse: ponowne użycie tego samego kodu (rozwiązania) do dopisania innych danych. Wystarczy bowiem powtórzyć ten sam request z innymi danymi np.:

request #1
Cookie: PHPSESSID=174lrg845ngs78g477s7m1q4i4

imie=Jan&login=janko&haslo=T4jn3H45lo&captcha=4158

request #2
Cookie: PHPSESSID=174lrg845ngs78g477s7m1q4i4

imie=Katarzyna&login=kasienka&haslo=5up3rT4jn3&captcha=4158

W ten sposób raz rozwiązany test CAPTCHA można użyć wielokrotnie, używając tego samego rozwiązania w połączeniu z tą samą sesją. Jeżeli więc nie przeładowujemy strony, a jedynie wysyłamy ciągle ten sam request np. używając burp lub curl, lekko modyfikując przesyłane dane, to ten skrypt nie zda egzaminu, bo na jednym i tym samym rozwiązanym teście CAPTCHA można przesłać wiele requestów i np. dodać wiele użytkowników do serwisu itp.
Rozwiązanie CAPTCHA przechowywane w sesji powinno być zmieniane/unieważniane po pierwszym użyciu.

2) CAPTCHA bypass: całkowite obejście mechanizmu CAPTCHA.
CAPTCHA jest ustawiane w Sesji w momencie wczytania pliku (obrazka) z kodem CAPTCHA. Jeżeli tego obrazka nie wczytamy, wówczas nie będzie ustawionej zmiennej Sesyjnej z kodem CAPTCHA.
Jeżeli teraz z danych POST wykasujemy część związaną z przesyłaniem kodu CAPTCHA, wówczas brak będzie CAPTCHA w Sesji i brak będzie CAPTCHA w przesyłanych danych POST, a więc brak==brak, dzięki czemu formularz zostanie zatwierdzony.

Aby się przekonać, wystarczy z requestu np.:

Cookie: PHPSESSID=174lrg845ngs78g477s7m1q4i4

imie=Jan&login=janko&haslo=T4jn3H45lo&captcha=4158

usunąc zawartość captcha=4158 oraz usunąć identyfikator sesji PHPSESSID=174lrg845ngs78g477s7m1q4i4. W tym momencie taki request zostanie uznany za poprawny (if ($_POST[‚kod’]==$_SESSION[‚captcha’])), bo nie przesyłamy rozwiązania CAPTCHA w danych POST i nie mamy kodu CAPTCHA zapisanego w Sesji (bo nie przesyłamy identyfikatora sesji, który przecież usunęliśmy).

Zachęcam Cię do zostawienia komentarza!

Ilość znaków: 0