Sesje w bazie danych

1

Witam, dotychczas do logowania użytkowników stosowałem "gołe" sesje z PHP, ale po uświadomieniu sobie bezpieczeństwa takiego rozwiązania, postanowiłem jak najszybciej to zmienić. Przekopałem sporo informacji na ten temat i chyba najlepszym rozwiązaniem jest zrobienie własnego mechanizmu sesji opartego o bazę danych. Niestety, ile ludzi tyle zdań jak to ma konkretnie wyglądać aby było bezpieczne (a przynajmniej bezpieczniejsze niż natywne sesje) i już sam nie wiem, czy dobrze rozumiem problem, dlatego prosiłbym Was o sprawdzenie mojego prostego rozwiązania. Do rzeczy. W bazie danych tworzę nową tabelę 'sessions' o następującej strukturze:

session_id user_id browser expiration
'expiration' to data i czas wygaśnięcia sesji (standardowo 1 godzina, chyba że użytkownik zaznaczy autologowanie).
Jeżeli użytkownik prawidłowo wpisał swój login i hasło, za pomocą polecenia md5(time()) generowany jest identyfikator sesji który, oprócz do bazy, wstawiany jest także do ciastka. Data wygaśnięcia tego ciastka jest oczywiście taka sama, jak przypisanej do niego sesji. Do sprawdzania czy użytkownik jest zalogowany stosuję tego typu funkcję (zabieram się do tej obiektówki "jak pies do jeża"):
function islogged()
{
	global $dbc; //połączenie z bazą

	if (isset($_COOKIE['logged']))
	{
		$sql = mysqli_query($dbc, "SELECT user_id FROM sessions WHERE session_id='$_COOKIE[logged]' AND browser='$_SERVER[HTTP_USER_AGENT]'");
		$row = mysqli_fetch_array($sql);
		if (!empty($row))
			return $row['user_id'];
	}

	return 0;
}

Czy to rozwiązanie ma w ogóle sens i jest w miarę bezpieczne?

0

jeśli działa i wiesz dlaczego, to ma sens, jeśli uda Ci się to obejść to nie jest bezpieczne. stań od strony włamującej się i zastanów się czy jesteś w stanie być zalogowanym nie znając hasła (jeśli tak to kiedy).

0

Dzięki za odpowiedź. Wydaje mi się, że powinno być dosyć bezpieczne, bo aby podszyć się pod czyjąś sesję cracker, tworząc ciastko, musiałby wiedzieć jak jest generowane id sesji, co do sekundy znać czas logowania jakiegoś użytkownika, a także wiedzieć z jakiej korzysta przeglądarki (zakładamy oczywiście, że nie ma dostępu do bazy :)). Jednakże czuję, że moja wiedza w tej materii jest mała, dlatego jeżeli piszę głupoty to proszę o wyrozumiałość i rozjaśnienie mi tej kwestii.

2

Ło matko! Kilka SQLi w jednym. Bardzo wskazane jest, żeby każdy początkujący webmaster w pewnym momencie dowiedział się o pełnej gamie podstawowych ataków, jakie mogą być wycelowane w jego aplikację. Zabezpieczyć się możesz za pomocą mysql_real_escape_string(), addslashes(), htmlentities() lub korzystając z funkcji działających podobnie. Oprócz tego mała uwaga dotycząca bezpieczeństwa:

Jeżeli użytkownik prawidłowo wpisał swój login i hasło, za pomocą polecenia md5(time()) generowany jest identyfikator sesji który, oprócz do bazy, wstawiany jest także do ciastka.

Race condition. Co jeśli dwóch użytkowników w tej samej sekundzie się zaloguje? Powinna tutaj być jakaś bezpieczna losowość i ewentualnie regenerowanie ID sesji tak długo aż trafi się faktycznie unikalny.

Radzę też nie bagatelizować danych takich jak referer czy user agent. Jeśli nie zachowamy ostrożności przy używaniu tych danych możemy spłodzić lukę typu XSS wycelowaną w administratorów lub SQLi wspominany wcześniej.

gienek napisał(a)

Zapomniałem o tym, dzięki. W takim razie w funkcji, oprócz istnienia ciastka, sprawdzę czy jego wartość ma 32 znaki. Chociaż może lepiej byłoby sprawdzić czy zawiera jakieś inne znaki niż litery i cyfry.

Niestety sprawdzenie czy wartość ciastka ma 32 znaki nie ratuje sytuacji.

Mała przeróbka ataku Marcina:
1' OR '2'='2' --aaaaaaaaaaaaaaaa
Coś takiego przejdzie bez problemu.

0

Właśnie po cichu liczyłem na twoją wypowiedź i spojrzenie na to wszystko chłodnym okiem, choć myślałem, że będzie ostrzej ;D Temat ataków oczywiście liznąłem przy okazji chociażby zabezpieczania formularzy, ale... było to dość dawno temu ;p Z tym user agent to nie wpadłbym na to, że może z niego napłynąć niebezpieczeństwo, jak widać trzeba mieć "oczy dookoła głowy".
Bardzo celna uwaga z tym id sesji. Może oprócz czasu dokleję tam też id użytkownika.

Dzięki za cenne wskazówki, teraz już chyba wiem jak to powinno wyglądać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1