Opracowanie bezpiecznej strategii logowania i uwierzytelniania PHP

Rozwijam system logowania i uwierzytelniania dla nowej strony PHP i czytam różne ataki i luki. Jest to jednak trochę mylące, więc chcę sprawdzić, czy moje podejście ma sens.

Planuję przechowywać następujące dane:

  • W sesji: user-id, hashed + salted HTTP_USER_AGENT

  • W pliku cookie i w bazie danych: random token, hashed + solted identyfikator

Na każdej stronie planuję zrobić:

  1. Jeśli sesja istnieje, Uwierzytelnij ją za pomocą tej funkcji. sprawdź, czy HTTP_USER_AGENT pasuje do przechowywanej sesji.

  2. Jeśli sesja nie istnieje, użyj pliku cookie do uwierzytelnienia. sprawdź, czy token i identyfikator w pliku cookie pasują do tych w bazie danych.

  3. Jeśli plik cookie jest nieprawidłowy lub nie istnieje, Poproś użytkownika o login.

Czy są w tym jakieś oczywiste wady? Tak długo, jak ustawiam limit czasu w ciastku, powinienem być dość bezpieczny, prawda? Czy coś mi umyka? Z góry dziękuję.
Author: Philip Morton, 2009-12-16

8 answers

Kilka losowych myśli:

  1. Co jeśli ukradnę plik cookie jednego z Twoich użytkowników (używając ataku XSS poprzez wstrzyknięcie kodu JS na Twoją stronę)? Wtedy upadnę w przypadku 2. i tym samym być w stanie się zalogować. IMHO, jeśli chcesz naprawdę bezpiecznego uwierzytelniania, nie używaj ciasteczek typu "Zapamiętaj mnie" do przechowywania poświadczeń użytkownika.
  2. jeśli przechowujesz dane uwierzytelniające w pliku cookie, nie przechowuj hasła Wyczyść.
  3. sprawdzanie HTTP_USER_AGENT jest dobrym pierwszym krokiem, aby zapobiec session hijacking, ale może mógłbyś połączyć to z adresem IP ? O wiele trudniej jest być na tym samym hoście niż cel, niż po prostu korzystać z tej samej przeglądarki.

Ale w każdym razie, dziękuję za poświęcenie czasu na zastanowienie się nad dobrym schematem uwierzytelniania. Wielu programistów PHP tego nie robi.

EDIT: dla przypomnienia, pozwól, że wyjaśnię tutaj: w tym dysku są dwa ciasteczka. Jeden jest ustawiany automatycznie przez PHP, aby propagować ID sesji (czasami, we zobacz strony umieszczające go w adresie URL, np. www.example.com/page.php?sessionId [ ... ]), a drugi stworzony przez Ciebie w celu przechowywania danych uwierzytelniających użytkownika i uwierzytelniania go po utracie sesji. Atakujący może ukraść plik cookie sesji i przejąć sesję (która ma ograniczony czas życia) lub ukraść plik cookie poświadczeń i uwierzytelnić go później.

 12
Author: Wookai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-17 14:14:52

Nie powinno być. sesja php jest przechowywana na twoim serwerze nie przez użytkownika. php simpily pozostawia plik cookie sesji wskazujący na niego. jeśli nie korzystasz z hostingu współdzielonego, sesja nie musi być nawet zahaszowana.

Joe

 2
Author: Joe Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-16 20:21:57

Przechowywanie pliku cookie w bazie danych to HORRILBE idea. Oznacza to, że jeśli atakujący miał lukę sql injection, mógł natychmiast uzyskać dostęp bez konieczności łamania zahaszowanego hasła.

Skoro o tym mowa, musisz użyć sha256 do haseł, jeśli używasz md5 (), jesteś technicznie podatny na atak i możesz otrzymać numer CVE.

Nigdy nie Generuj własnych identyfikatorów sesji, używaj session_start () i $_SESSION Super global.

To jest bezpieczne sposób na przekierowanie ludzi. Jeśli nie umrzesz po header() reszta kodu php jest nadal wykonywana, mimo że nie jest wyświetlana przez normalne przeglądarki (hakerzy nadal go widzą :)

header("location: index.php");
die();
Jeśli Bezpieczeństwo Cię myli, nie pisz systemów bezpieczeństwa. Ludzie napisali ponad 1000 systemów logowania tylko dla PHP, a większość z nich jest podatna na ataki. Ten projekt ma bezpieczny system uwierzytelniania: http://code.google.com/p/michael-the-messenger/downloads/list
 2
Author: rook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-17 02:34:52

Zależy jak bezpiecznie chcesz być..

Luki między stronami: Powiedzmy, że inna strona kieruje przeglądarkę do przesłania formularza do witryny, która robi coś takiego jak publikowanie spamu (lub gorzej), jeśli użytkownik jest już zalogowany na przesyłanie formularza będzie działać. Musisz sprawdzić referer i wygenerowany Ukryty formID dla każdego formularza, aby w pełni przed tym chronić.

Po drugie: jeśli masz duży lub średni ruch, sesje można powtórzyć lub nawet odgadnąć, sprawdzałbym przed second hand generowany identyfikator, który jest przechowywany w plikach cookie użytkowników.

 1
Author: MindStalker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-16 20:32:52

Schemat wydaje się niepotrzebnie skomplikowany na kilka sposobów, ponieważ dodatkowa złożoność nie daje Ci nic w zakresie funkcjonalności lub bezpieczeństwa.

  1. wszelkie dane przesyłane przez przeglądarkę (np. pliki cookie, User-agent) są fałszywe. Sprawdzanie User-agent pomoże tylko wtedy, gdy atakujący znajduje się za tym samym NAT co fałszywy użytkownik, a atakujący używa innej przeglądarki, ale nie myśli, aby zmienić User-agent.
  2. Sessions Przechowuje identyfikator sesji po stronie klienta za pomocą Plików cookie lub parametr zapytania URL. Jeśli chcesz przedłużyć żywotność sesji, użyj session_set_cookie_params aby utrzymać plik cookie sesji na dłużej.

User-agent nie jest tajnymi danymi, więc hashowanie jest niepotrzebne.

Ataki, których session cookie+checking remote IP nie wychwyci to:

  1. atakujący stoi za tym samym NAT co użytkownik
  2. ataki typu Blind injection, w których atakujący podszywa się pod adres IP użytkownika. Pomimo tego, że są tylko do zapisu, nadal mogą zrobić kilka uszkodzenia.
  3. [4]}ataki wykorzystujące własną przeglądarkę użytkownika, takie jak[21]}cross-site request forgery (CSRF).

2) można zapobiec, jeśli można wypracować sposób wysłania wyzwania do przeglądarki użytkownika, na które należy odpowiedzieć przed wypełnieniem żądania, ale jest to trudne, gdy nie napisałeś do klienta. Dzięki AJAXOWI można to zrobić. 3) (Jak zauważył MindStalker) można zapobiec, sprawdzając nagłówek Referer, który działa, ponieważ ataki CSRF nie mają możliwość wpływania na dowolne nagłówki, a XMLHttpRequest nie powinien zezwalać na ustawianie nagłówka Referera(zgodnie ze standardem W3C , choć implementacje mogą nie być zgodne). Z iframes, może być możliwe obejście sprawdzania Referer. Ponadto nagłówek Referer może być zablokowany po stronie klienta.

 1
Author: outis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-19 21:53:19

Większość witryn używa tylko sesji PHP; dane sesji ($_SESSION) znajdują się w Pliku na Twoim serwerze. Wszystko, co jest wysyłane do przeglądarki to identyfikator sesji. Pamiętaj, aby regenerować sesję każdego żądania ( session_regenerate_id). Nie musisz wysyłać dwóch ciasteczek ani niczego innego.

Jest to mniej podatne na przechwytywanie sesji, ponieważ każde żądanie jest nowym identyfikatorem, więc stary przechwycony przez atakującego jest bezużyteczny.

Najlepszym rozwiązaniem byłoby oczywiście używaj protokołu SSL przez całą sesję.

 1
Author: Jacob Greenleaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-19 22:19:30

IMHO ważne jest również, aby informacje o sesji zostały zmienione po pomyślnym zalogowaniu. Zapisywanie informacji o sesji w bazie danych nie jest zapisywane z powodu zastrzyków.

 0
Author: DrDol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-19 23:08:03

-użyj sha1 z solą - oczywiście musisz zdefiniować, że każdy formularz nie jest bezpieczny, więc używany token dla każdego formularza. Że tworzysz każdy wpis formularza i oczyszczasz go za pomocą preg_match. Proces zwany kanalizacją.

 0
Author: Bryan Paul B. Quinto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-01 06:54:19