Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sesje, jakie metedy najbezpieczniejsze
Forum PHP.pl > Forum > PHP
Avatarus
Witam
Stworzyłem prymitywny system logowania opartego na razie tylko o sesje (bez tabel i cookies). Działa ona tak:
na początku każdego pliku który wyświetla stronę (np index.php, news.php, artykul.php) mam funkcje session_start()
Potem jest logowanie. Ściąga dane z formularza (login i hasło), potem jest zapytanie SQL, jeśli znajdzie takiego usera w bazie to ustawia zmienne sesyjne:

  1. <?php
  2. $_SESSION['user']=tu są dane z tabeli
  3. $_SESSION['pass']=tu są dane z tabeli (oczywiście hasło hashowane md5)
  4. $_SESSION['level']=tu są dane z tabeli odnośnie poziomu usera. Czy to user, mod czy admin
  5. ?>


Przy wylogowywaniu jest robione session_destroy()
Czy takie coś jest bezpieczne? Chyba nie. Można przecież jakoś ukraść sesje.
Jak byście wy napisali sprawniejszy (i co ważniejsze) BEZPIECZNIEJSZY system sesji.

Z góry dziękuje na pomoc, naprawdę mi zależy na tym
Pozdrawiam.
nowotny
Poszukaj trochę, tu na forum i w google... znajdziesz multum przykładów z objaśnieniami...
em1X
1) Domyślnie sesja korzysta z Cookie smile.gif Zaczynając sesję PHP wysyła do użytkownika Cookie z numerem sesji.
2) Danych sesyjnych nie można ukraść. Znajdują się na serwerze. Chyba, że ktoś "ukradnie" komuś numer sesji, wtedy wstawia go sobie do swojego Cookie i .. jest podszyty pod obcą osobę.
3) Nie musisz hashować hasła w sesji. Jak pisałem dane są niedostępne dla klientów.
sobstel
Cytat(em1X @ 5.02.2008, 11:03:05 ) *
2) Danych sesyjnych nie można ukraść. Znajdują się na serwerze. Chyba, że ktoś "ukradnie" komuś numer sesji, wtedy wstawia go sobie do swojego Cookie i .. jest podszyty pod obcą osobę.


niestety można. oprócz sposobu, który sam zauważyłeś to pogooglaj sobie o innych zagrożeniach takich jak session poisoning, session exposure czy session injection. dotyczy to zwłaszcza hostingów współdzielonych.
Avatarus
no to ciągniemy temat dalej. Poczytałem to forum i znalazłem info że taka metoda jest dość bezpieczna.
1. po zalogowaniu tworzy się Cookies o jakieś tam nazwie. W treści dajemy jakiś unikany hash np. sha1(time().'nick')
Te dane zapisujemy też do tabeli sesji (id,nick,haslo,unikalny hash,ilosc blędnych logowań)
No i teraz jak ktoś wchodzi na stronie to sprawdzane jest czy jest cookies, jeśli tak to sprawdzane jest czy dane w nim zgadzają się z nickiem i haslem podamy z formularza no i z unikalnym hashem z bazy sesji.
Jeśli nie ma cookie to tworzy się normalna sesja (co tworzy się tez po sprawdzeniu cookies)

No i teraz moje pytanie, czy taka metoda jest bezpieczna? Kolumna "ilosc blednych logowań" eliminuje chyba wszystkie próby ataku typu brute force.
Odnośnie tych hashy to doczytałem jeszcze że samo md5 lub sha1 to za mało. Trzeba kombinować żeby naszego hasła nie można było wyszukać w tęczowych tablicach.
Czy parametr httponly w setcookie() daje decakto większe bezpieczeństwo? Broni tylko przez wyświetleniem go z poziomu JS?
Jednak dalej obawiam się o to
Cytat
session poisoning, session exposure czy session injection. dotyczy to zwłaszcza hostingów współdzielonych.


Czy można tutaj zastosować również session_regenerate_id, to chyba ukróci ataki które są nastawione na kradzież ID sesji...bo dane Id było by ciągle zmieniane.

Co o tym sądzicie?
sobstel
Cytat
Kolumna "ilosc blednych logowań" eliminuje chyba wszystkie próby ataku typu brute force.


i przy okazji daje możliwość zablokowanie konta użytkownika, np. gdy chcemy mu zrobić na złość ;-)

co do dalszej części postu, session_regenerate_id przy każdym żądaniu to całkiem dobre rozwiązanie, ale może być zbyt obciążające przy większej liczbie użytkowników (zresztą często większe bezpieczeństwo osiągamy kosztem wydajności, niestety). w sumie możesz znależć złoty środek odtwarzając id co kilka żądań (ale zawsze to rób przy zmiane uprawnień na wyższe) i koniecznie zwróć uwagę na parametr TRUE funkcji session_regenerate_id, w przeciwnym razie regeneracji na nic się nie zda.

możesz także razem z parametrami przwchowywać hasha (z jakimś saltem) liczonego ze wszystkich wartości, to wtedy nawet jak ktoś się dobierze do plików sesyjnych, będzie miał dodatkową przeszkodę. można też szyfrować dane w pliku np. używając mcrypt.

jednak zawsze musisz się zastanowić czy potrzebujesz aż taki poziom bezpieczeństwa. tak naprawdę nie ma stałych ścisłych reguł, więc nie wpadaj w pułapkę próby stworzenia jednego uniwerslanego rozwiązania problemu. zawsze to zależy od aplikacji, nad którą właśnie pracujesz.
nowotny
Cytat(sopel @ 5.02.2008, 19:20:11 ) *
i przy okazji daje możliwość zablokowanie konta użytkownika, np. gdy chcemy mu zrobić na złość ;-)

Wtedy możemy wysłać użytkownkowi maila co i jak i link do odblokowania... winksmiley.jpg
Avatarus
przeczytałem właśnie PDFa z php.net: http://www.acros.si/papers/session_fixation.pdf
Jest tak dokładnie wytłumaczone jak działają Ataki Session Fixation, Session Hijacking
Tutaj dowiedziałem się o kilku innych sposobach.
Kurcze nie wiedziałem że jest tyle sposobów....

No więc tak po tych lekturach (i kilku innych) wiem że:
- nie należy umieszczać ID sesji w linku
- nie należy umieszczać ID sesji w cookie
- należy unikać serwerów współdzielonych
- nie należy klikać w linki od obcych z powodu parametru Referral, który może wyciągnąć info o Sesjach

Co należy robić:
- stosować nowatorskie metody hashowania takie na które nie ma słowników (do sha1 i i md5 już są)
- należy unikać przekazywania danych odnośnie usera w zmiennych sesyjnych
- dokładnie filtrować dane od usera tzn sprawdzać czy pola które mają być int są faktycznie int. Teksty traktować strip_tagiem i innymi funkcjami tego pokroju
- zabezpieczać newralgiczne zapytania SQL przez dodanie np mysql_real_escape_strings


Dobra a teraz kilka pytań:
skoro używam (na razie) tylko session_start() i session_destroy() to czy istnieje możliwość zaatakowania tej sesji? Nie można chyba np dodać do linku SID z numerem sesji i automatycznie ją przejąć (jeśli Id faktycznie istnieje)?
Czy można zmusić sesje do tego by nie przyjmowały ID sesji z zewnątrz? tzn linki, cookie i formy?
Czy da się zabezpieczyć jakoś wyciekanie danych poprzez użycie przez atakującego opcji Referral z spreparowanego linku?

Co do blokowania usera jeśli zaloguje się źle X razy to można dodać pole IP do tej tabeli wtedy blokuje tylko IP typa który ma konkretne IP.

Mam nadzieje że ktoś mi poradzi biggrin.gif

Pozdrawiam
ucho
Możesz jeszcze zapamiętywać IP i np UserAgent podczas tworzenia nowej sesji i sprawdzać przy następnych requestach czy się wszystko zgadza ( bo żadnego powodu żeby się to zmieniło nie ma).
.chudy.
IP może sie zmieniać jeżeli będziesz się łączyć przez proxy. Wg mnie dobrym rozwiązaniem jest przechocywanie sesji w bazie danych, wtedy opcja z serwerami współdzielonymi już odpada.
Avatarus
no dobra ale mam teraz problem natury logicznej....
skoro w Cookie będzie przechowywany jakiś hash (tylko nie hash Id sesji itp) ale jakiś inny losowy ciąg np transformacja daty+ nazwa usera + coś tam jeszcze....
no to jeśli ktoś skradnie cookies to ma pełen dostęp do sesji. Jeśli wprowadzić sprawdzanie IP, zdenerwuje to masę userów, jak wiadomo spora część ma neo....Jeśli w zamian zastosować user_agent to też dość łatwo można takie coś obejść bo jak wiadomo większość userów ma przeważnie najnowsze wersje swoich przeglądarek (nie wliczając w to userów IE ^^)
ja można to jeszcze poprawić? Załóżmy że sesja ma być podtrzymywana jeśli jest z tego samego komputera (albo bardzo podobnego smile.gif ) Chce tak skonfigurować dane sesji żeby tylko powołane osoby miały do niej dostęp, niestety jak wiadomo sprawdzanie IP odpada...

no i jeszcze jedno. jak sprawdzacie później w skryptach czy ktoś jest zarejestrowany?
Ja mam teraz na zasadzie jeśli istnieje $_SESSION[user] i $_SESSION[user_level] to zalogowany w innym wypadku nie. Oczywiście wszystkie zmienne sesji są unsetowane przed session_destroy tak dla pewności.
Myślicie że tak może być?
sobstel
Cytat
No więc tak po tych lekturach (i kilku innych) wiem że:
- nie należy umieszczać ID sesji w linku
- nie należy umieszczać ID sesji w cookie


hmm, to gdzie je zamierzasz umieścić?questionmark.gif

Cytat
Czy można zmusić sesje do tego by nie przyjmowały ID sesji z zewnątrz?


tak, np.

  1. <?php
  2. if (!isset($_SESSION['created']))
  3. {
  4. $_SESSION['created'] = true;
  5. }
  6. ?>
specialplan
Osobiscie dane sesji trzymam w bazie danych i ciagle je porownuje z tym, co sie dzieje na stronie. Konstruktor klasy sesji odpala zapytanie do bazy sprawdzajace, czy wszystko gra. W cookie trzymane jest tylko ID sesji. Istnieje drugie ciastko, ktore odpowiedzialne jest za przekazywanie serializowanych danych sesji. Jako parametrow zgodnosci sesji uzywam ID sesji, IP uzytkownika, ID uzytkownika, przegladarka i czas sesji (kontrola stanu bezczynnosci). Ciastko sesji przechowuje jedynie hashowane ID uzytkownika. W zasadzie baza danych robi reszte. Nie bede rozwodzil sie nad struktura autoryzacji, ktora jest dosc skomplikowana. System przetestowany zostal na kilkudziesieciu serwisach, wiele z ktorych ciesza sie duza popularnoscia i jak dotad nie bylo zadnych problemow, rowniez z wydajnoscia.
Avatarus
Cytat
hmm, to gdzie je zamierzasz umieścić?

w tabeli

nie wiem czy dobrze rozumie z tymi ID sesji bo teraz nie ma to trochę sensu... (pewnie jak zwykle coś pomieszałem)

po co session ID? no prześledźmy mój tok myślenia...
jeśli nie ma cookies to twórz nową sesje sprawdza logowanie , loguje zapisuje dane do tabeli sesji i cookie...
no i teraz jest cookie i sprawdza czy specjalnie spreparowane dane z cookie pasują do tabeli sesyjnej. sprawdza też czy to ta sama osoba sprawdzając user_agenta itp...jeśli tak to tworzy nową sesje i tyle.
Coś błędnego w moim toku rozumowania? może inaczej co jest błędne? biggrin.gif
specialplan
Musisz miec unikalny ID na podstawie ktorego porownasz dane z cookie z danymi w tabeli.
Avatarus
no dobra ale wytłumaczcie mi czy te session ID to po prostu taki abstrakt który sami wymyślamy np u mnie Id było by powiedzmy md5(date('U').sha1('salt')
Czy przez session Id rozumie się konkretny ID sesji przydzielane przez serwer?

Jeśli to pierwsze to można spokojnie wprowadzić takie coś w php.ini

session.use_only_cookies = 1

lub

php_value session.use_only_cookies 1
php_value session.use_trans_sid 0

Mam racje?
specialplan
To, co podales, sluzy raczej do ograniczenia przekazywania ID sesji tylko do ciasteczek. Natywnie, PHP samo generuje ID sesji. Dla swoich potrzeb zmienilem ten mechanizm i generuje ID sam. Tak jak mowisz, jest to wartosc abstrakcyjna. Osobiscie nie korzystam z mechanizmu sesji oferowanego przez PHP.
Avatarus
no czyli tak jak napisałem w wyżej będzie to w pełni działać tak? Korzystam z własnych unikalnych Id więc ciężej będzie je dorwać
specialplan
Podmiana ID nie bedzie raczej mozliwa, gdy ID sesji w cookie porownywane jest z tym w bazie. No chyba, ze ktos wlezie do bazy.
Avatarus
no czyli mogę powoli zacząć zabierać się za pisanie tego skryptu biggrin.gif

Wielkie dzięki wszystkim, bardzo cenie te forum. Na prawdę nie spodziewałem się tutaj panuje tak miła atmosfera smile.gif

Pozdrawiam
bełdzio
to może tak btw http://www.beldzio.com/bezpieczenstwo-mechanizmu-sesji.freez
Avatarus
Bełdzio czytam twój blog smile.gif Fajnie i zwięźle piszesz. Ten artykuł też czytałem właśnie z niego mam to info o id tylko z cookies biggrin.gif

Dzięki.
specialplan
@Beldzio

W zasadzie moja klasa sesji jest zbudowana podobnie. Dodalem tylko jeszcze metode do porzadkowania (czytaj: 'kasowania') starych sesji z bazy.
Jarod
@Avatarus: Mam własną klasę (handler) sesji. Wszystkie sesje zapisywane są w bazie. Jest też metoda gc, która usuwa przeterminowane sesje. Czas trwania sesji ustawia się w pliku konfiguracyjnym. Mógłbym się pokusić o napisanie metody generującej id, ale nie mam czasu. IMHO bezpieczny sposób.
Pozdrawiam
sammael
Jak chcecie uniknąć zapisu SIDa w ciastkach i linkach jednocześnie !? Panowie to se ne da.
Jeśli chodzi o zabezpieczenie to najlepiej sprawdzać
parę IP-SID przy każdym requeście. Nawet jeśli komuś na tacy podacie SIDa to wywołanie
przez niego skryptu z identycznym SIDem skończy się automatycznym wylogowaniem.
Co ciekawe takie sztuczki można sobie zapisywać i nagradzać dowcipnisi bananami.
Avatarus
no dobra ale jak ktoś ma neo to co? Szlag trafi jego zapamiętywanie sesji...
specialplan
Niekoniecznie - chyba, ze w czasie trwania sesji rozloczy sie z siecia i polaczy ponownie. Inna sprawa to zapamietywanie uzytkownika na dluzej, co niektore serwisy oferuja, by nie trzeba bylo logowac sie z kazda wizyta. Ja tego jednak nigdy nie stosuje.
Avatarus
no właśnie sęk w tym że potrzebuje logowanie na dłużej.
Idea taka. Strona skupia pewną społeczność internetową. Dla nich logowanie automatycznie jest bardzo dobrym rozwiązaniem bo nie chce im się logować ciągle. Spora część posiada Neostradę (tak wynika ze statystyk). Co może zwykły zalogowany user? Zasadniczo jego możliwości na razie ograniczają się do: pisania postów na shout boxie, pisania komentarzy, wysyłania obrazków itp. Niektóre części serwisu są zablokowane tylko dla zarejestrowanych i zalogowanych. Więc jak widać nie ma tu żadnych takich newralgicznych danych i można zastosować zapamiętywanie logowania.
Dlatego odrzucam model z zapisywaniem IP.
bełdzio
Cytat(specialplan @ 7.02.2008, 10:59:45 ) *
@Beldzio

W zasadzie moja klasa sesji jest zbudowana podobnie. Dodalem tylko jeszcze metode do porzadkowania (czytaj: 'kasowania') starych sesji z bazy.

zobacz ostatnią funkcje u mnie ;-)

Cytat(sammael @ 7.02.2008, 17:53:55 ) *
Jak chcecie uniknąć zapisu SIDa w ciastkach i linkach jednocześnie !? Panowie to se ne da.

da smile.gif można jeszcze sida przesyłac jako ukryte pole formularza :-)
specialplan
O, faktycznie jest. No to mielismy bardzo podobny pomysl:)
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.