PHP/Sesje: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Nie podano opisu zmian
Yrazec (dyskusja | edycje)
Dodałem znaczniki source i usunąłem zamykające ?> w przykładowych skryptach
Linia 12:
Czas na trochę praktyki. Aby zainicjować mechanizm sesji, wystarczy wywołać funkcję ''session_start()'', najlepiej na początku naszej aplikacji. Od tego momentu do naszej dyspozycji zostaje oddana superglobalna tablica ''$_SESSION'' - wszystkie zapisane do niej dane są przesyłane między kolejnymi żądaniami. Popatrzmy na pierwszy, bardzo prosty przykład licznika odwiedzonych już podstron:
 
<nowikisource lang="php"><?php
session_start(); // 1
Linia 25:
echo 'Odwiedziłeś już '.$_SESSION['licznik'].' podstron!'; // 4
?></nowikisource>
Oto analiza:
# Inicjujemy sesje
Linia 38:
Zatem, jak taki system logowania działa? Kiedy sesja jest już załadowana, skrypt sprawdza zapisany w niej ID użytkownika. Jeżeli jest on większy od zera, ktoś jest już zalogowany i wystarczy tylko pobrać skądś dane jego profilu. W przypadku ID równego 0 mamy do czynienia z kimś anonimowym. Tu, w zależności od sytuacji możemy mu wyświetlać ogólnodostępne treści albo formularz logowania. Pisanie skryptu zaczniemy od stworzenia sobie namiastki bazy danych. Będzie nią tablica ''$uzytkownicy'' przechowująca loginy oraz hasła użytkowników. Ponadto napiszemy funkcję ''czyIstnieje()'' znajdującą ID użytkownika o podanym loginie i haśle lub '''false''', kiedy takowy nie istnieje. Hasła naturalnie haszujemy poznanym już algorytmem sha1:
 
<nowikisource lang="php"><?php
$uzytkownicy = array(1 =>
Linia 62:
// Jeżeli doszedłeś a tutaj, to takiego użytkownika nie ma
return false;
} // end czyIstnieje();</nowikisource>
 
Teraz zaczniemy właściwy skrypt. Zainicjujemy sesję i obsłużymy sytuację pierwszej wizyty - w takim wypadku gościa oznaczymy jako osobę anonimową (niezalogowaną):
 
<source lang="php">
<nowiki>
// Wlasciwy skrypt
Linia 75:
// Sesja się zaczyna, wiec inicjujemy użytkownika anonimowego
$_SESSION['uzytkownik'] = 0;
}</nowikisource>
 
Krótka piłka - ID większy od 0? Ktoś jest zalogowany:
 
<source lang="php">
<nowiki>
if($_SESSION['uzytkownik'] > 0)
{
Linia 86:
}
else
{</nowikisource>
 
Jednak jeśli nie jest, to musimy zaprogramować zarówno pokazywanie formularza logowania, jak i autoryzację użytkownika na podstawie danych z niego. Zaczynamy od tej drugiej opcji. Korzystając z funkcji ''czyIstnieje()'' pobieramy ID użytkownika. Jeżeli jest on różny od '''false''', wpisujemy go do sesji, tym samym logując go.
 
<source lang="php">
<nowiki>
// Niezalogowany
if($_SERVER['REQUEST_METHOD'] == 'POST')
Linia 106:
}
else
{</nowikisource>
 
Kiedy dane nie nadeszły z formularza, znaczy to, że trzeba go wyświetlić:
 
<source lang="php">
<nowiki>
echo '<form method="post" action="sesje_2.php">
Zaloguj sie: <input type="text" name="login"/>
Linia 117:
}
}
?></nowikisource>
 
I gotowe. Wszystko fajnie, wszystko pięknie, nasza witryna sobie działa, użytkownicy się logują, dodając coraz to nowe treści, lecz pewnego dnia dostajesz e-maila z ostrzeżeniem, że ktoś włamał się do serwisu i wszystko rozwalił. Co nawaliło? Czyżby zawiódł mechanizm sesji?
Linia 126:
Włamania wykorzystujące dziury w mechanizmach sesji mają swoje fachowe nazwy. Pierwszą z nich jest ''Session Fixation''. Jej działanie jest bardzo proste. Wykorzystujemy tutaj właściwość, że kiedy podamy skryptowi jakiś nieistniejący ID sesji, PHP automatycznie dorobi dane i nie przejmie się tym, że tak naprawdę to my go wygenerowaliśmy, a nie jakiś algorytm losująco-mieszający. Teraz popatrz: podszywasz się pod pracownika jakiegoś serwisu internetowego i każesz nieświadomemu użytkownikowi odwiedzić jakiśtam adres, najlepiej wymagający zalogowania. Do adresu URL doczepiasz ciąg ''?PHPSESSID=abcdef''. "abcdef" jest wymyślonym przez nas identyfikatorem. Kiedy użytkownik posłusznie się zaloguje, jest zdany na naszą łaskę. Mamy ID jego sesji i możemy działać tak, jakbyśmy byli nim.Jeszcze więcej cwaniactwa i możemy uzyskać nawet sesję administratora, co dla serwisu oznacza oczywiście katastrofę. Aby się przed tym zabezpieczyć, wystarczy po zainicjowaniu mechanizmu sesji dokleić bardzo prosty kod:
 
<nowikisource lang="php"><?php
session_start();
Linia 136:
}
 
?></nowikisource>
 
Przy tworzeniu nowej sesji, dzięki funkcji ''session_regenerate_id()'' mamy pewność, że sesja dostanie losowy ID. Teraz nawet, jeżeli podamy zmyślnie ''?PHPSESSID=abcdef'', nic nam to nie da, bo PHP i tak sobie wszystko wygeneruje po swojemu i zostaniemy w tym samym miejscu, co byliśmy. Jednak nie spoczywaj jeszcze na laurach. ID nadal może zostać wykradziony. Wystarczy, że jakiś ciamajda skopiuje znajomemu link do jakiegoś zasobu, mając przy tym wyłączone ciastka. Oczywiście w linku znajdzie się wtedy jego LOSOWY identyfikator sesji, który w ten sposób zostanie ujawniony przed światem. Znajomy może teraz wędrować sobie po serwisie wykorzystując sesję ciamajdy. ''session_regenerate_id()'' tutaj nie zadziałała, bo przecież ta sesja już istnieje. Ataki tego rodzaju określa się mianem ''Session Hijacking''. Zabezpieczenie się przed nimi także jest proste. Wystarczy w sesji przesyłać np. adres IP komputera wraz z nazwą przeglądarki, spod których została ona utworzona, a następnie porównywać je przy kolejnych wizytach z danymi dostarczonymi przez serwer. Jeżeli wystąpi niezgodność, ktoś próbuje użyć cudzej sesji.
 
<nowikisource lang="php"><?php
session_start();
Linia 157:
}
?></nowikisource>
 
Powyższy przykład zawiera łatki przeciwko obu włamaniom (co prawda w przypadku tej drugiej o wiele lepszym rozwiązaniem byłoby utworzenie sesji na nowo w przypadku niezgodności, niż obwieszczanie całemu światu naszego "odkrycia"). Pamiętaj jednak, że najsłabszym ogniwem jest zawsze człowiek. Jeżeli hacker zdobędzie twoje hasło, zabezpieczenia na nic się nie zdadzą, chyba że akurat masz stały adres IP i tak sobie wszystko napisałeś, że na twoje konto można się tylko z niego logować.