28
2012
Zabezpieczenie formularza cz.1 – token i klucz prywatny
Każdy właściciel/programista strony internetowej z możliwością rejestracji konta lub formularzem kontaktowym spotka się ze spamem, a dokładnie spamBotem :) Masową, śmieciową wysyłką formularzy lub fałszywych rejestracji kont.
Na szybko myślimy, jak zabezpieczyć formularz… rozwiązania są proste i na pewno nie należy do nich autystyczna CAPTCHA! Nikt z nas przecież nie lubi domyślać się „Co jest napisane na tym obrazku o_O ???!!!!”
Przedstawię serię krótkich artykułów z prostymi metodami zabezpieczania formularza, bez absorbowania szarych komórek użytkownika naszej strony www ;)
Na wstępie zaznaczam, że poniższa metoda przyda się tylko osobom nie mających dostępu do użycia sesji oraz JavaScript. Działa tylko w przypadku, gdy bot wcześniej nie wygeneruje dla siebie formularza.
Token, klucz prywatny i publiczny
Opis działania
Całość opiera się na operowaniu trzema wartościami: tokenem, kluczem prywatnym oraz kluczem publicznym. Ich deklaracja, przesyłanie i walidacja poprawności.
- Deklarujesz w stałych lub zmiennych wartość klucza publicznego oraz prywatnego (np. jest to ciąg losowo wygenerowanych znaków). Klucz prywatny nie jest widoczny (jest zaszyty w skrypcie), dzięki niemu sprawdzisz poprawność tokena. Tylko klucz publiczny i token uwidaczniasz, przesyłając go w formularzu.
- Generujesz token z klucza prywatnego oraz klucza publicznego.
- Dodajesz dwa inputy typu hidden w formularzu widocznym dla użytkownika na stronie www.
- W inputach umieszczasz wartość wygenerowanego tokena oraz wcześniej zadeklarowaną wartość klucza publicznego.
- Użytkownik wysyła wypełniony przez siebie formularz.
- Skrypt PHP, który odbiera dane z wysłanego formularza waliduje przesłany token na podstawie przesłanego klucza publicznego oraz ukrytego klucza prywatnego.
Przykładowy kod PHP + HTML
Część odpowiedzialna za wygląd formularza.
1 2 3 4 5 6 7 8 9 10 |
<form action="..." method="post"> <!-- tutaj pozostałe pola, które uzupełnia użytkownik --> <?php $publicKey = rand()%9; // generowanie klucza publicznego $privateKey = 0.9; // deklaracja klucza prywatnego $token = sha1( $publicKey * $privateKey + $privateKey ); // generowanie tokena ?> <input type="hidden" name="publicKey" value="<?php echo $publicKey; ?>" /> <input type="hidden" name="token" value="<?php echo $token; ?>" /> </form> |
Część w miejscu, gdzie skrypt odbiera dane z wysłanego formularza.
1 2 3 4 5 6 7 8 9 10 11 |
<?php $publicKey = $_POST['publicKey']; // przesłany klucz publiczny metodą POST $privateKey = 0.9; // deklaracja klucza prywatnego, można jednokrotnie zadeklarować, gdzieś w nadrzędnym pliku w include $token = sha1( $publicKey * $privateKey + $privateKey ); // generowanie ponownie tokena, na podstawie przesłanego klucza publicznego oraz ukrytego klucza prywatnego if ( $token == $_POST['token'] ) { // sprawdzenie czy token przesłany zgadza się z tokenem wygenerowanym na nowo // wykonuj pozostały kod związany z odbiorem danych z przesłanego formularza, np. zapytanie SQL, wysłanie maila } ?> |
Dodatkowe informacje
- Klucz prywatny i publiczny można deklarować według własnego pomysłu. Powyżej jest tylko przykład. Najlepiej klucze zadeklarować jako stałe w pliku, który będzie inkludowany na stronie z formularzem i skryptem odbierającym z niego dane.
- Przesyłane dane można dodatkowo sprawdzać według ich typu (sanitize), np. tylko liczba, tylko litery i znaki itp. Używając funkcji
preg_replace()
. - Token należy kodować w jedną stronę funkcją haszujacą, np. md5 lub bezpieczniejszym sha1.
- Wzór na generowanie tokena jest dowolny. Może być to np. zwykłe łączenie ciągów. Im więcej danych w tokenie tym lepiej. Ze zwykłego łączenia ciągu znaków korzystając serwisy z płatnościami. Nie trzeba się bawić w generowanie liczb, jak powyżej :)
- Powyższą metodę łatwo obejść. Wystarczy, że bot wygeneruje najpierw dla siebie formularz z uzupełnionym kluczem publicznym i tokenem i następnie go prześle. Zadziała tylko w przypadku, gdy bot dobija się od razu do skryptu odbierającego dane. Dlatego też zalecam go w przypadku braku możliwości użycia sesji lub JavaScript.

2 komentarze + Dodaj komentarz
Dodaj komentarz
O mnie
Najnowsze wpisy
- Drzewo kategorii – budowa struktury od dołu do góry
- PHPExcel – export + import pliku XLS
- WordPress + Polylang – Tworzenie klasy CSS z ID strony/wpisu w wybranym języku
- Mailing – Poprawna konstrukcja szablonu maila HTML/CSS i prawidłowy wygląd w programie pocztowym
- Szukasz programisty PHP dla e-commerce?
Według mnie to bardzo słabe zabezpieczenie, każdy szanujący się robot do rozsyłania spamu to obejdzie. Przecież wystarczy zapuścić prosty test w Sellenium i to rozszyfruje (bo tu nawet nie ma rozszyfrowywać tylko wygenerować stronę). Jakby istniało coś bezpieczniejszego od interakcji z userem to dawno by coś takiego powstało. Dlatego reCaptcha jest uważana za jedno z najbezpieczniejszych rozwiązań.
OK, ten skrypt jest bardzo prostą metodą.
Działa tylko przy bezpośrednim wysyłaniu danych do skryptu.
Aby to obejść, bot musiałby najpierw wejść na stronę z wygenerowanym formularzem, sczytać dane z inputów i następnie je przesłać. Tak wiem, nie jest to trudne ;)
Lepszym rozwiązaniem jest użycie tokena w sesji.
Ale dzięki za zwrócenie na to uwagi ;)