Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]System Autoryzacji - wasze najlepsze spodoby
Forum PHP.pl > Forum > PHP
b_chmura
Witam

Potrzebuje zrobić system autoryzacji. Chciałem się was zapytać jakie są najlepsze sposoby, jak najlepiej się zabezpieczyć przed możliwymi włamami, gdzie i jak przetrzymywać dane ze taki i taki user jest zalogowany?
Interesują mnie tylko najlepsze/najbezpieczniejsze rozwiązania.

Liczę na waszą kreatywność.

Pozdrawiam
Chmura

EDIT
Dotychczas korzystałem z link dziś nie wydaje mi się to najlepszym rozwiązaniem...
Fixus
hmm na co powinno się zwrócić uwagę:
1. hashowanie hasła
2. ograniczyć ilość wpisywanych znaków
3. zabezpieczyć przed wprowadzeniem niebezpiecznych znaków
4. korzystać z troszkę mniej standardowych nazwa tabel i pól jak pojedyńcze słowa "user", "login" czy "password"
chiken
co do przechowywania danych, to przetrzymuje je w sesji, login i haslo,

i przy kazdym odswiezeniu strony / przejsciu na inna sie loguje / sprawdza czy uzytkownik ma uprawnienia,

nigdy np nie trzymam informacji ze uzytkownik sie zologowal, i tylko to pozniej po kazdym odswiezeniu sprawdzam
Prph
Cytat(chiken @ 12.09.2007, 13:19:17 ) *
nigdy np nie trzymam informacji ze uzytkownik sie zologowal, i tylko to pozniej po kazdym odswiezeniu sprawdzam


Dlaczego przechowywanie loginu i hasla bedzie bezpieczniejsze niz samo "zalogowany"?
NuLL
Przechowywanie hasla to czysta glupota bo kto go potrzebuje ? Tak naprawde jedyna rzecza ktora powinna byc w sesji to id uzytkownika oraz te dane ktorych sie czesto uzywa np do wypisania - np. login,email czy nazwa ekranowa tak nie pobierac ich za kazdym zadanie z bazy danych.
qqrq
Ja bym jednak za każdym wejściem na stronę sprawdzał użytkownika. Np. jedna zmienna sesji to będzie login/email/id czy coś podobnego (unikalnego sie rozumie), a druga to zahashowana konkatenacja loginu i hasła (albo czegokolwiek innego, byle nie tego samego, co trzymamy w pierwszej zmiennej).
b_chmura
a jest taka możliwość żeby ktoś się podszył pod jakąś sesje?
żeby ktoś odczytał co sie znajduje w sesji?
qqrq
No właśnie można, aczkolwiek nie jest to takie proste (ogólnie sesje są po to, żeby nikt niepowołany tam się nie wpieprzał, ale wiadomo - dla chcącego nic trudnego smile.gif ). Dlatego ten cały hash...
b_chmura
tak mi się wydawało dlatego czekam na dalsze sugestie jak bezpiecznie się zalogować i przechowywać dane o użytkowniku by tylko po poprawnym zalogowaniu ukazały mu sie odpowiednie dane.

a może by tak napisać własny hash?
qqrq
Własny hash? Przecież masz md5. Hasha nie odczytasz - to jest tak jakby "szyfrowanie w jedną stronę".
b_chmura
szczerze sie przyznam ze nie znam dokładnej definicji "hash'a" ale chodziło mi o własne zakodowanie danych wraz z funkcją odpowiedzialną za odkodowanie..

np zamiana liter na cyfry i wykonanie jakiegoś działania matematycznego
qqrq
Rozumiem o co Ci chodzi, ale weź pod uwagę to, że twój szyfr ktoś może odszyfrować. Funkcji hashującej odszyfrować się nie da. A jak sprawdzać? Za każdym wywołaniem strony bierzesz dane z sesji (załóżmy, że w zmiennych sesji masz login i md5(login.hasło) - zhashowana konkatenacja, że się tak wyrażę... smile.gif ), po czym pobierasz dane z bazy (u nas login i hasło, tak żeby login pasował do hasła) i porównujesz (patrzysz czy md5(login_z_bazy.hasło_z_bazy) == hash_z_sesji). I tyle.
b_chmura
to nie zabije bazy? jak jej przyjdzie hashowac wszytkie loginy i hasła... może od razu przy rejestracji zastosować tą kombinacje?
legorek
O przepraszam, mając hash masz spore szanse odzyskania hasła. Poczytajcie o tęczowych tablicach. W internecie są też strony typu http://md5.rednoize.com/ które zawierają 50 000 000 najpopularniejszych haseł i hashy. Więc to nie jest takie trudne. Najlepszą obroną jest solenie hashowanych stringów.

Ale to była taka mała dygresja.

Wracając do tematu. Najlepsze są rozwiązania najprostsze.

Przy rejestracji zapisujesz w bazie: id, login, hash hasła.
Prz próbie zalogowania robisz: SELECT * FROM user WHERE `login`='$login' AND `pass`=MD5('$pass');
Jeśli to zapytanie zwróci ilość rekordów różną od 1 to znaczy, że coś jest nie tak: nie ma usera, złe hasło etc.
Jeśli wszystko jest OK, apisujemy do sesji np id i login. Nie ma sensu niczego więcej, chyba że jest to dla Ciebie wygodne.
Teraz, żeby sprawdzić czy user jest zalogowany sprawdzamy czy te dane istnieją w sesji.
Aby wylogować usera usuwamy jest z sesji.

Najsłabszym ogniwem tego rozwiązania jest zapytanie do bazy, mamy tu dane które pochodzą od użytkownika. Dlatego najaważniejsz rzeczą jest taka konfiguracja serwera i fitlrowanie zapytań, aby uniemożliwić SQL injection.

To wszystko, nie ma sposobu, żeby oszukać taki system jeśli jest dobrze zaprojektowany.

Istnieją jeszcze dwa niebezpieczeństwa, jednemu możesz zapobiec, drugiemu możesz tylko próbować:
1) Zła konfiguracja serwera, która pozwoliłaby w jakiś sposób uzyskać atakującemu do katalogu z sesjami (czy do bazy z sesjami, jeśli masz własny mechanizm obsługi sesji) Ale szczerze wątpie żeby istniał tak lamowaty admin serwera smile.gif
2) Zdobycie przez atakującego identyfikatora sesji ofiary. To już poważniejszy problem, bo atakujący może działać na koncie ofiary. Musisz tak przygotować swój serwis, aby nie dało się dokonać Code Insertion. (konkretnie chodzi o wstrzyknięcie javascriptu lub innego języka skryptowego który pozwala na dostęp do ciasteczek) Ale to już jest temat rzeka, bo nawet największe serwisy sobie z tym nie zawsze radzą.

Pozdrawiam!
qqrq
legorek => No tak, ja mówiłem o teorii, czyli o funkcji hashującej jako funkcji z dążącym do 0 prawdopodobieństwem kolizji. Zawsze można zamiast md5 wybrać coś "lepszego".

b_chmura => Z podanych przez legorka "zagrożeń" naprawdę ciężko wyeliminować to drugie.

Cytat
Ale to już jest temat rzeka, bo nawet największe serwisy sobie z tym nie zawsze radzą.


Prawda... aaevil.gif
Prph
Cytat(qqrq @ 12.09.2007, 16:59:49 ) *
No właśnie można, aczkolwiek nie jest to takie proste (ogólnie sesje są po to, żeby nikt niepowołany tam się nie wpieprzał, ale wiadomo - dla chcącego nic trudnego smile.gif ). Dlatego ten cały hash...


Moja sesja: id = 5, login = prph, haslo = *****;

Kradniesz moja sesje.

Twoja sesja to: id = 5, login = prph, haslo = *****;

Wiec, czy sprawdzisz, czy w sesji jest ustawione "zalogowany", czy sprawdzisz haslo to wyjdzie na to samo. No pomijam, ze baza dostaje w tylek na dzien dobry.
qqrq
W tym przypadku wszystko jedno, chodzi o to, żebyś nie mógł sobie sam wpisać (jakkolwiek byś to zrobił) zmiennych sesji. Jak jest tylko zmienna "zalogowany" to żaden problem, a tak musisz znać dane konta (login, hasło, etc.).
Zresztą ja spotykałem się głównie z takimi rozwiązaniami, chociażby osCommerce, i tak to zawsze kazało mi robić szefostwo z pracy, że tak się na autorytety powołam... smile.gif

A co do tego, że "baza dostaje w tyłek" - nie dostaje aż tak bardzo. Ten jeden SELECT przy wczytywaniu strony wielkiej krzywdy nie robi.
chiken
A wiec dlaczego za kazdym razem sprawdzam czy dana osoba jest w bazie danych, przy kazdym odswiezeniu:

jesli osoba sie zaloguje, i dane ze zalogowany bedzie przechowywac w sesji, to taka osoba moze byc zalogowana nawet przez rok jesli bedzie sobie strone odswiezal, i np jesli np admin zablokuje uzytkownika, lub zmieni mu jakies dane ktore sa przechowywane w sesji, to i tak nic nie da , jesli czlowiek jest zalogowany.

Dlatego zawsze sprawdzam czy dane login-haslo zgadza sie z tym w bazie, i danych uzytkownika nie przechowuje w sesji tylko w normalnej zmiennej, i aktualizuje za kazdym odswiezeniem
Sedziwoj
Sesja ma dwa czasy życia, jeden pomiędzy odświeżeniami drugi od założenia. Więc sesja może się przeterminować np. po dniu nie ważne że ciągle odświeżasz.
Przypadek kiedy użytkownik wyleciał a ma aktywną sesje jest na tyle rzadki, że nie warto męczyć systemu ciągłym sprawdzaniem.
Ale to wszystko już zależy od systemu który wymaga autoryzacji... bo można sprawdzać uprawnienia do danej akcji za każdym razem itp. itd.
qqrq
No cóż, temat rzeka, jak widać... W gruncie rzeczy proponuję używanie PEAR::Auth. Sprawdzone, rozwijane i projektowane przez tęższe umysły niż niżej podpisany...
marcini82
Cytat
2) Zdobycie przez atakującego identyfikatora sesji ofiary. To już poważniejszy problem, bo atakujący może działać na koncie ofiary. Musisz tak przygotować swój serwis, aby nie dało się dokonać Code Insertion. (konkretnie chodzi o wstrzyknięcie javascriptu lub innego języka skryptowego który pozwala na dostęp do ciasteczek) Ale to już jest temat rzeka, bo nawet największe serwisy sobie z tym nie zawsze radzą.

Zaczynajac sesje, mozna zapisac w niej IP klienta i przy kazdym odswiezeniu sprawdzac, czy sie zgadza. Jesli w trakcie jej trwania ktos przechwyci jej id, to i tak nic mu to nie da, jesli nie bedzie sie laczyl z serwerem z tego samego publicznego IP co ofiara. Czyli odpornosc na tego typu ataki znacznie wzrasta.
qqrq
Patrz mój poprzedni post. W PEAR::Auth są chyba wszystkie możliwe zabezpieczenia przed co popularniejszymi atakami. Wystarczy zajrzeć do plików.
marcini82
Moze i sa, ale wykorzystanie PEAR::Auth w jakiejs tam konkretnej aplikacji nie kazdemu musi pasowac, wiec dobrze znac poszczegolne mechanizmy, zeby moc je samemu zastosowac w troche innym kontekscie.
Fixus
@marcini82 - korzystajac z twojego pomyslu i idac kawalek dalej mozna stworzyc osobne pole w tabeli do ktorego po zalogowaniu bedzie zapisywane IP uzytkownika a po wylogowaniu bedzie czyszczone. Czy to dobre rozwiazanie?

ps. przepraszam za brak polskich znakow ale cos mi klawiatury rypla
marcini82
No to juz zalezy od tego, czy korzystasz z tablicy $_SESSION, czy tez dane na temat sesji wolisz przechowywac w bazie danych.
Baza danych wymaga wiecej zachodu, ale daje wiecej mozliwosci.
b_chmura
Czyli tak:

Gdy użytkownik się loguje jego login oraz shash'owane hasło zapisujemy w sesjach
inne unikalne dane takie jak: ip, przeglądarka zapisujemy do bazy

przy przechodzeniu na inną stronę/odświeżaniu sprawdzamy wszystkie te dane czy czasem się nie zmieniły. Jeśli uległy zmianie prosimy o powtórne zalogowanie.

Jak na mój gust zabezpieczenie w pytę
Sedziwoj
Cytat(marcini82 @ 13.09.2007, 18:44:37 ) *
No to juz zalezy od tego, czy korzystasz z tablicy $_SESSION, czy tez dane na temat sesji wolisz przechowywac w bazie danych.
Baza danych wymaga wiecej zachodu, ale daje wiecej mozliwosci.


Mylisz się, nie wymagają więcej zachodu session_set_save_handler" title="Zobacz w manualu PHP" target="_manual


@b_chmura
Bez sensu, uparłeś się na to hasło w sesji... a robisz prosto logowanie login+hash hasła w bazie -> tak -> w sesji ustawiamy zalogowany=1 i ip=... i porównujemy ip w sesji z tym z którego przychodzi żądanie.
(oczywiście mowa tym jak zalogować użytkownika, nie o logowaniu kiedy, z jakiego adresu itp. itd.)
marcini82
@Sedziwoj
No moze to nie jest jakas magia, ale w kazdym razie trzeba jakas tam obsluge tych sesji w bazie napisac.

@b_chmura
Nie o to mi chodzilo. Jak na moj gust to warto przechowywac dane albo za pomoca sesji dostarczanych przez php, albo napisac wlasny mechanizm, np. w sposob jaki podal Sedziwoj. Ale po co rozbijac: login tu, a IP tam... i robi sie z tego galimatias. Po co ci to IP w bazie? No chyba, ze korzystasz z normalnych sesji, a dodatkowo chcesz zapisywac wszystkie odwiedziny w bazie. Ale chyba nie o tym byla mowa... A to haslo w sesji to ci chyba tez niepotrzebne.
qqrq
Zgadzam się z kolegą wyżej co do możliwego zminimalizowania galimatiasu... Do bazy zapisujesz tylko jeśli chcesz monitorować w jakiś sposób odwiedziny, tzn. np. zliczać je, wyświetlać na stronie kto jest zalogowany itp. Wszystko najlepiej w sesjach. A co - opinii jak widzisz dużo. Moja - p. w. smile.gif
.radex
nie wiem czy to już było bo nie przeczytałem całego tematu, ale dołożę swoje -

Zabezpieczenie przed floodowaniem (max. 3 próby na 10 min z jednego IP/hosta + np. max. 15 prób na godzinę z jednego IP/hosta, a pozniej czasowy ban)
Blodo
Pamietajcie tylko ze jesli chodzi o dane sesyjne w php, to sa one zapisywane na serwerze a nie w cookiesach. Tak wiec jakies bezpieczenstwo jest jesli chodzi o podstawianie danych. Jedyne czego tak naprawde nalezy sie bac przy sesjach to kradziezy session id, jak uzywasz domyslnych sesji w php to poprostu session_regenerate_id() oraz upewnic sie zeby nie bylo session id w urlach (choc wtedy zakladasz ze twoj uzytkownik ma wlaczone cookiesy, jak nie ma to klapa).
Bazowanie na IP nie za bardzo sie sprawdza, bo niektorzy maja internet co potrafi zmienic IP nawet w trakcie polaczenia, a wtedy uzytkownika wylogowywuje. Jeszcze inni pracuja sobie z poza lanu, a wtedy kilku (lub kilkuset zaleznie od lanu) uzytkownikow moze miec to samo IP. Ogolnie nigdy nie bedzie to stu procentowo bezpieczne, ale zawsze te 98% czy iles jest. Jeszcze wieksze bezpieczenstwo mozna uzyskac korzystajac z SSL.

Polecam rowniez przeczytanie tego arta:
http://phpsec.org/projects/guide/4.html
Nattfarinn
Właściwie, ja w zmiennych sesyjnych (umiejscowionych jak na razie w tablicy $_SESSION) przechowuję wygenerowane unikalne ID sesji (którym jest md5 z połączonego: microtime(), loginu i daty ostatniego logowania) oraz ID użytkownika. Resztę zmiennych sesyjnych (takich jak data wygaśnięcia, uprawnienia etc.) przechowuję w bazie w odpowiednich komórkach.

Przy każdym odświeżeniu sprawdzam czy istnieje w bazie sesja o odpowiednim ID sesji należąca do użytkownika o odpowiednim loginie - jeśli jest, sesja jest utrzymana i autoryzacja jest uzyskana. Jeśli nie ma, sesja jest zakończona a autoryzacji oczywiście nie ma, przy czym dla pewności ID sesji i ID użytkownika (jeśli jakieś były przechowywane w $_SESSION choć nie pasujące), są niszczone.

Dodając jedno zapytanie, można przy każdym poprawnym odświeżeniu sesji (utrzymaniu autoryzacji) generować nowe ID sesji. To też jakiś sposób na zapobiegnięcie próbom podszycia się pod sesję (chociaż losowość ID sesji sama w sobie i tak powinna w znacznym stopniu uprzykrzyć życie włamywaczom).

Do tego tak napisać kod, by uniemożliwić wszelkiego rodzaju Code Injection'y, i mamy całkiem sprawny i bezpieczny system utrzymania sesji. Nie ma oczywiście zabezpieczeń doskonałych, każdy system ma swoje zalety i wady. Ja swojego systemu zabezpieczeń złamać nie potrafię ale to nie znaczy, że nikt nie potrafi. Nie ma systemów nie do złamania.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.