Podstawy uwierzytelniania i sesji

Ogólnie problem wygląda następująco - tworzę pewną aplikację, która będzie (a przynajmniej taki jest plan :D) działać na serwerze. Jej użytkownicy będą komunikować się z nią za pomocą strony internetowej i programu-klienta. Jestem teraz na poziomie etapie projektowania bazy danych (o bazach mam pojęcie minimalne, o serwerach już nie wspominając). Doszedłem teraz do problemu uwierzytelniania, sesji i ogólnego bezpieczeństwa. Przeczytałem trochę o ogólnych sposobach uwierzytelniania hasłem, hashowaniu, soleniu, ciasteczkach i atakach. Mam teraz następujące pytania:

  • Jak ostatecznie powinna wyglądać tabela użytkowników? Czy powinno to być coś w rodzaju (login, email, hash, sól, inne dane)?
  • Gdzie powinna znajdować się funkcja hashująca i soląca? Po stronie klienta, czy serwera?
  • Jak powinna wyglądać bezpieczna komunikacja użytkownika i serwera?
  • Czy porównywanie hashy to zwykłe if(hash1 == hash2)?
  • Jaki algorytm hashujący?
  • Jak powinien wyglądać bezpieczny system sesji? Trzymać informacje w ciasteczkach, czy może jeszcze po stronie serwera, a może połączenie obu?

Znacie może jakieś niecodziennie spotykane zabezpieczenia przeciwko idiotyzmowi użytkowników, jeżeli chodzi o uwierzytelnianie?

Dostęp do bazy będzie miał tylko jeden program. Za komunikację z użytkownikami i uwierzytelnianie będzie odpowiadał jeden z jego modłów. Wszystko po stronie serwera będzie pisane w C++, włącznie z CGI, baza danych to PostgreSQL.

Jeżeli znacie jakieś dobre źródła związane z tematem, posługiwania się serwerami, zabezpieczaniem ich przed atakami, używania C++ jako CGI albo cokolwiek przydatnego, to podajcie linki:

Tutaj kilka linków ode mnie:

https://stackoverflow.com/questions/3715920/about-password-hashing-system-on-client-side

Q: Jak ostatecznie powinna wyglądać tabela użytkowników? Czy powinno to być coś w rodzaju (login, email, hash, sól, inne dane)?

A: Tak

Q: Gdzie powinna znajdować się funkcja hashująca i soląca? Po stronie klienta, czy serwera?

A: sól to po prostu losowa wartość. Generujesz ją po stronie serwera, bo wtedy wiesz na ile możesz polegać na generatorze. Hash również po stronie serwera (jeśli generujesz go po stronie klienta, to znaczy że możesz uwierzytelnić się samym hashem, więc jeśli twoja baza danych wycieknie, to każdy będzie mógł się zalogować, w przypadku liczenia na serwerze będzie musiał odwracać hashe, żeby dostać hasło - ograniczy to potencjalne szkody)

Q: Jak powinna wyglądać bezpieczna komunikacja użytkownika i serwera?

A: Nie do końca rozumiem pytanie. Dobrze, żebyś ją szyfrował (HTTPS), jak uściślisz pytanie to napiszę więcej.

Q: Czy porównywanie hashy to zwykłe if(hash1 == hash2)?

A: Tak

Q: Jaki algorytm haszujący

A: Obecnie https://en.wikipedia.org/wiki/Scrypt tylko musisz wybrać takie parametry, żeby nie zabił serwera.

Q: Jak powinien wyglądać bezpieczny system sesji? Trzymać informacje w ciasteczkach, czy może jeszcze po stronie serwera, a może połączenie obu?

A: W ciasteczku masz tylko ID sesji, serwer dba o to, by je powiązać z sesją na serwerze. Oczywiście powinieneś pamiętać np. o czyszczeniu cookie przy logowaniu (każda zalogowanie powinno skutkować innym ID sesji).

Q: Znacie może jakieś niecodziennie spotykane zabezpieczenia przeciwko idiotyzmowi użytkowników, jeżeli chodzi o uwierzytelnianie?

A: Uwierzytelnianie dwuskładnikowe, jeśli masz na myśli przylepianie kartek z hasłami do monitora.

 

Czyli klient wysyła hasło jako zwykły tekst, serwer soli, hashuje i porównuje z hashem z bazy? Jeżeli tak, to jak zabezpieczyć się, przed przechwyceniem hasła? 

Jak powinna odbywać się komunikacja, tak żeby żaden podmiot trzeci nie mógł odczytać wiadomości, jeżeli ją przechwyci? Chodzi mi właśnie o to szyfrowanie.

Czyli serwer tworzy sesję, przesyła ID klientowi, klient przy każdym żądaniu wysyła ID sesji, serwer porównuje otrzymane ID z tym, które posiada i jeżeli się zgadza, reaguje na żądanie? Czy serwer powinien sprawdzić przy tym jeszcze IP lub inaczej zweryfikować, czy numerem sesji posługuje się klient? 

https? Poczytaj o certyfikatach SSL.

Po https. Serwer wystawia skonfigurowany certyfikat, przeglądarka sama go odbiera, sprawdza czy trzecia strona jest zaufana jak tak, to masz “zieloną kłódkę” jak nie to wyjątek bezpieczeństwa i prośbę o akceptacje certyfikatu. Następnie wszystkie wiadomości nadawane na https będą automatycznie szyfrowane kluczem z tego certyfikatu. Odczytać wiadomość może tylko ten kto ma drugi pasujący klucz, czyli serwer.

Nie ma to sensu nagłówki ramki tcp/ip nie ulegają szyfrowaniu i można je zmieniać (nie są szyfrowane, bo kolejne routery muszą wiedzieć jak przekierować tę wiadomość do celu). Innymi słowy ktoś może przechwycić wiadomość - jeśli była nie szyfrowana - to ja zmienić (powiedzmy podmienić numer konta w banku, tak, żeby przelew który robisz poszedł do niego), a następnie ustawić, że odbiorcą odpowiedzi zwrotnej i tak jesteś nadal ty, https i tyle.

@kostek135 Dzięki, to dużo wyjaśnia. Jednak dalej nie wiem, jak powinien działać mechanizm sesji. Czy to mogłoby wyglądać np. tak: po uwierzytelnieniu, serwer wysyła ID sesji, ID jest przechowywane w ciasteczku i wysyłane przy każdym żądaniu, serwer po otrzymaniu żądania porównuje otrzymane ID z ID przypisanym do uwierzytelnionego konta. Tak to działa? 

Praktycznie każdy język programowania ma już zaimplementowany mechanizm sesji i zrobi to za ciebie. $_SESSION w PHP, javax.servlet.http.HttpSession w Java, etc. Ale tak wewnętrzna implementacja sesji będzie oparta o ciastka.

Będę używał C++, więc w tym wypadku to raczej biblioteka.

Tak z ciekawości - jak wygląda uwierzytelnianie i sesje na DP? Widziałem tutaj HTTPS tylko przy logowaniu.

Tak, znaczy tyle, że sesja jest podatna na to by ją wykraść przez atak typu mitm. Ale to już popadanie w paranoję, bo na co to komu. Szyfrowanie jest zrobione tylko przy logowaniu, bo wtedy przekazywane jest hasło plain-text’em. Przechwycenie sesji umożliwi atakującemu tylko na dostęp tylko do tego serwisu (w zasadzie nic specjalnego). W przypadku wycieknięcia hasła mogą być narażone też inne konta użytkownika, np. bankowe (użytkownicy mają tendencję, do posiadania tych samych haseł wszędzie).

Cóż, nie sądzę, żeby to było popadanie w paranoję. Jeżeli przechwyci się sesję, to można nieźle narozrabiać. Co prawda, tylko na danym serwisie, ale to i tak dużo.

Za trudny do wykonania atak, żeby komuś opłacało się hackować konto na DP. Popadanie w paranoję.