[PHP] Skrypt logowania

0

Witam,
Napisałem (ulepszyłem :)) skrypt logowania. Po zalogowaniu, pobierany jest id użytkownika z bazy, a następnie przypisywany do zmiennej $_SESSION['zalogowany']. Nie wiem, może jestem ślepy i nie zauważyłem czegoś w kodzie, ale dlaczego nic się do tej zmiennej nie przypisuje? ;)

<?php
     session_start();
     $salt = sha1(...);
     $conn = mysqli_connect(...);
     $query1 = "SELECT * FROM Users WHERE Login='".mysqli_real_escape_string($conn, sha1($_POST['login'].$salt))."' and Haslo='".mysqli_real_escape_string($conn, sha1($_POST['haslo'].$salt))."'";
                $wynik1 = mysqli_query($conn, $query1);
                $ile1 = mysqli_num_rows($wynik1);
     $query2 = "SELECT ID FROM Users WHERE Login='".mysqli_real_escape_string($conn, sha1($_POST['login'].$salt))."'";
                $wynik2 = mysqli_query($conn, $query2);
                $ile2 = mysqli_fetch_row($wynik2);
                      $_POST['id'] = $row[0];
                      
     $_POST['ip'] = $_SERVER['REMOTE_ADDR'];
     $query3 = "SELECT * FROM bans WHERE ip='".$_POST['ip']."'";
     $wynik3 = mysqli_query($conn, $query3);
     $ile3 = mysqli_fetch_array($wynik3);
     $proby = $row[1];
     $data = $row[2];
     if($proby == 3 && $data > 10) {
         echo ('Przekroczyłeś ilość dozwolonych błędów w logowaniu. Spróbuj ponownie za 10 minut.');
         exit();
     }
     if($ile1 == 1)
     {
         $_SESSION['zalogowany'] = $_POST['id'];
         echo ("<b>Zostałeś zalogowany jako '".$_POST['login']."'.Jeśli przekierowanie nie nastąpi w ciągu 5 sekund, kliknij<a href=\"index.php\">tutaj</a>.");
     } elseif ($ile1!==1) {
         echo ('Nieprawidłowe dane.');
         $query4 = "INSERT INTO bans VALUES('".$_POST['ip']."', '".$_POST['proby']."', '".$_POST['data']."')";
         $wynik4 = mysqli_query($conn, $query4);
         $query5 = "SELECT * FROM bans WHERE ip='".$_POST['ip']."'";
         $wynik5 = mysqli_query($conn, $query5);
         $ile5 = mysqli_num_rows($wynik5);
         if($ile5 == 1) {
         $_POST['proby'] = $_POST['proby'] +1;
         $_POST['data'] = 10;
        $query6 = "UPDATE bans SET proby='".$_POST['proby']."', czas='".$_POST['data']."' WHERE ip='".$_POST['ip']."')";
        $wynik6 = mysqli_query($conn, $query6);
        exit();
     }
     }
?>

Mam też jeszcze jedno pytanie. Na końcu kodu jest blokada na ip (nie dokończona ;)), dlaczego zmienna $ile5 zawsze wynosi 0, jeśli w tabeli mam zapisany rekord?
Tabela w bazie wygląda tak: IP, proby (ilość niepoprawnych prób logowania) i czas (data ostatniej próby)</b>

0

Napisałem Ci w mailu. Używasz $row, a nigdzie wcześniej go nie przypisujesz. Poza tym nie musisz stosować tylu zapytań. Wykorzystaj pierwsze nie tylko do weryfikacji loginu i hasła, ale także do pobrania ID użytkownika (jeśli zwróci jakieś rekordy, tj. jeśli login i hasło się zgadzają).

Tak w ogóle to dobrze, że zainteresowałeś się bezpieczeństwem. Jest znacznie lepiej niż było: masz mysqli_real_escape_string i zahashowane hasła z saltem.

0

Ta, dopiero zauważyłem że dostałem drugiego maila ;)

Zauważyłem ciekawą rzecz. Jak hasła nie są hashowane, to logowanie odbywa się normalnie, a jak są hashowane, to zmienna $ile1 jest równa 0 zamiast 1. Czemu tak jest?

0

A może w tabeli Users w kolumnie Haslo przechowujesz hasła, a nie ich hashe...? Przy rejestracji użytkowników musisz wpisać do bazy danych hash hasła, a nie samo hasło (pamiętaj, by zarówno przy odczycie, jak i zapisie do bazy danych hashować hasło z tym samym saltem). W celu uniknięcia takich pomyłek możesz nawet zmienić nazwę kolumny z Haslo na Hash_hasla.

0

Dzięki, miałem tak zrobione, tylko że zapomniałem dodać .$salt w jednym miejscu...tyle się tego narobiło, że ciężko się nie pogubić ;)

Wszystko już działa. Oprócz tej blokady, nadal nie wiem, czemu zmienna $ile5 jest równa 0 :P A tak z ciekawości, co będzie jeśli ktoś się włamie i zdobędzie pliki php? Gdzieś czytałem, że można jakoś to zrobić. Przecież wtedy ten ktoś zobaczy dane do bazy MySQL i będzie mógł zdobyć hasła. Da się coś z tym zrobić?

0

@Perykles:
Z tym saltem to proponuję Ci napisać funkcję np. passwordHash($password) i potem wszędzie jej używać. Zwracałaby ona sha1($password . $salt). Wtedy miałbyś gwarancję, że wszędzie gdzie użyjesz tej funkcji hash będzie taki sam.

Co do wykradnięcia bazy danych to od tego są właśnie hashe. Wykradnie Ci hashe, a nie same hasła. Ponieważ używasz salta, nie będzie mógł użyć tzw. tablic tęczowych, by z hashów odtworzyć hasła i wykorzystać je w innych serwisach.

0

Wszystko już działa. Oprócz tej blokady, nadal nie wiem, czemu zmienna $ile5 jest równa 0 :P

Strzelam, że pole ip w tabeli bans jest kluczem głównym lub ma ograniczenie unique. Nie widzę obsługi błędów, więc strzelam, że nawet nie wiesz, że insert to tabeli bans odbywa się tylko raz, a potem mysqli_query zwraca błędy.

Poza tym widzę pewną niekonsekwencję: tabela bans wygląda tak, jakbyś każdą próbę chciał logować w osobnym rekordzie. Więc po co Ci tam pole proby?

Proponuję taki algorytm:

  1. błędne dane logowania
  2. sprawdź ilość prób logowania z tego ip (Select count(*) from bans where ip=...)
    3a. jeśli większa niż ustalone 10 - wywal info, że nie możesz się logować
    3b. jesli mniejsza niż 10 - zrób insert kolejnego rekordu dla tego ip.

Poza tym pewnie przyda Ci się timestamp w tabeli bans. Żebyś nie blokował kogoś w nieskończoność. Czyli w punkcie 2 wyszukiwałbyś rekordów dla danego ip, które są nie starsze niż na przykład 30 minut.

1 użytkowników online, w tym zalogowanych: 0, gości: 1