Czy sesje są bezpieczne?
Chciałbym tu poruszyć temat bezpiecznego logowania do sajtu opartego na PHP. Okazuje się, że to nie takie proste jak by się mogło zdawać. No ale zacznijmy od początku:
Po pierwsze musimy zdawać sobie sprawę z tego, że login i hasło
- zna użytkownik - można się włamać "na Mittnicka"
- "zna" komputer użytkownika (możliwość keyloggerów, ostatnio pojawiły się też exploity na przegladarki umożliwiające fałszowanie zawartości paska adresu - klient mysli, że wszedł na właściwą stronę a jest na stronie spreparowanej)
- każde urządzenie pośrednie pomiędzy komputerem usera a serwerem (atak man-in-the-middle, wszelkie podsłuchy)
- hasło przechodzi przez skrypty PHP - można podstawić własny skrypt
- hasło jest zapisane gdzieś na serwerze - można podejrzeć
- webmaster i twórca sajtu na pewno mają jakieś backdoory pozwalające na zmianę hasła jeśli user go zapomni.
Standardowo logowanie wygląda tak:
user wypełnia formularz z loginem i hasłem, jest on wysyłany metodą POST do serwera, tam jest weryfikowana poprawność i otwierana sesja.
Każde odwołanie się usera do serwisu powoduje najpierw sprawdzenie ważności sesji i jeśli jest ok -> wyświetlenia strony serwisu.
Po zakończeniu pracy z serwisem user powinien się wylogować i sesja powinna zostać zniszczona.
W jaki sposób należy się bronić przed wykradzeniem hasła?
- Uświadamiać swoich userów, że np. zapisywania hasła na kartce jest głupotą, podawanie go nie/znajomym także nie jest zbytnio szczęśliwym pomysłem.
- Uświadamiać swoich userów aby nie ciągneli z netu śmieci i surowo karać "po premii" za takie wykroczenia. Bardzo często synek pracownika potrafi wiele zrobić z siecią firmową...
- posiadać wystarczająco bezpieczną sieć, wykrywanie intruzów (IDS) i wszelkich podsłuchów, stosować szyfrowane połączenie klient-serwer (HTTPS)
- Dbać o bezpieczeństwo własnego serwera, uniemożliwić podglądanie plików z hasłami innym userom. Rozdzielić katalogi tymczasowe z sesjami różnych sajtów.
- Hasła należy szyfrować algorytmem haszującym, czyli takim, który nie pozwala odszyfrować hasła. Bardzo dobrym przykładem jest md5(). Ale co ciekawe znajomość loginu/hasła wcale nie jest potrzebna do tego aby przejąć uprawnienia zalogowanego usera!
Jak wspomniałem wcześniej po sprawdzeniu na serwerze ważności loginu i hasła tworzona jest sesja. Czyli w PHP tworzone jest ciastko PHPSESSID=jakiś numer. Jeżeli będziemy znali ten numer to bez trudu skorzystamy z tego, że ktoś inny akurat się zalogował.
Aby przejąć ten numer wystarczy wstawić kawałek javascriptu wywołujący nasz_skrypt.php?PHPSESSID=odczytany numer z ciastka. Np. w księdze gości, na forum - wszędzie tam gdzie można wstawić jakiś tekst - wyświetlenie odpowiednio spreparowanego tekstu spowoduje uruchomienie javascriptu i tym samym przejęcie uprawnień przez włamywacza. Rozwiązaniem jest tutaj striptags() i wycinanie przynajmniej javascriptu z tekstu. Dodatkowo należy zapisywać w sesji numer IP z którego nastąpiło logowanie i porównywać z numerem IP odwiedzającego stronę przy każdym następnym wejściu. - Wszelkie backdoory, a jest nimi na przykład możliwość edycji haseł w bazie danych (phpMyAdmin) powinny być bardzo dobrze zabezpieczone.
Oczywiście to, że user po zakończeniu pracy powinien się poprawnie wylogować jest utopią. Nawet ja, muszę się przyznać, to olewam i po prostu zamykam przeglądarkę. Dlatego należy stosować dodatkowe sprawdzenie przy logowaniu - czy user poprzednio się poprawnie wylogował i czy przypadkiem na ten sam login i hasło ktoś inny już nie jest zalogowany - jeżeli user zamknie nieprawidłowo sesję to niech teraz grzecznie poczeka aż ona wygaśnie i dopiero wtedy będzie mógł się zalogować ponownie. Oczywiście należy wziąć poprawkę na userów, którym Bill zawiesza kompa a TePsa zamyka połączenie z internetem.
Dodatkowe wodotryski, które podnoszą nieco bezpieczeństwo to:
- ograniczenie ilości nieudanych logowań z danego IP na jednostkę czasu
- blokowanie loginu po N nieudanych próbach logowania
- wymuszanie zmiany hasła po N dniach
- historia haseł uniemożliwiająca stosowanie wymiennie tylko 4 haseł (wiosna,lato,jesień,zima)
- sprawdzanie jakości hasła, jego długości, wymuszanie znaków specjalnych i liczb, sprawdzanie czy pasuje do "słownika" haseł. (John The Ripper)
- blokowanie loginu pracownika, który odchodzi z pracy lub idzie na urlop
- blokowanie możliwości logowania poza godzinami pracy i spoza sieci wewnętrznej firmy.
- przypisanie numeru/ów IP do loginu.