C, PHP, VB, .NET

Дневникът на Филип Петров


* Таймер за активност на потребителска сесия

Публикувано на 15 ноември 2008 в раздел ОСУП.

Както вече споменахме в статията за фиксиране на потребителски сесии, е добре приложенията, които пишем, да имат собствен таймер за активност, който е независим от настройките на сървъра. За щастие това се оказва доста лесна задача, тъй като всички езици за програмиране ни дават възможност за достъп до системния часовник на сървъра. В PHP ще реализираме тази функционалност чрез функцията time(). Тя връща броя секунди изминали от началото на "UNIX епохата", т.е. от 1 януари 1970. Нека преправим вече разгредания пример така, че да прекратява сесията ако тя е била неактивна повече от пет минути:

<?php
	session_start();
	session_regenerate_id(true);
?>
<html>
<head>
	<title>WorldBank.dom session page</title>
</head>
<body>
<?php

	$timeout = 5 * 60; // 5 минути
	$curtime = (int)time();
	if (isset($_SESSION['last_active'])){
		if ($curtime-$_SESSION['last_active'] > $timeout){
			echo 'Session timeout';
			session_destroy();
			return;
		}
	}
	$_SESSION['last_active'] = $curtime;

	echo 'session id is: ';
	echo session_id();
	echo '<br>';
	if (!isset($_SESSION['counter'])){
		$_SESSION['counter'] = 0;
	}
	else{
		$_SESSION['counter']++;
	}
	echo 'counter: ';
	echo $_SESSION['counter'];
?>
</body></html>

За да проверите примера намалете стойността на $timeout на 5 (т.е. 5 секунди) и отворете страницата. Направете няколко пъти refresh и ще видите, че всичко работи нормално. Ако обаче изчакате 6 или повече секунди и дадете refresh, то ще се получи session timeout.

Чрез такъв таймер може да предположим, че на атакуващият ще му е значително по-трудно да фиксира сесия, тъй като той трябва да я поддържа активна. Ние можем да го затрудним още повече, като добавим таймер за максимален живот на сесия. Такива таймери не са подходящи за всякакъв вид услуга, но в повечето случаи намират приложение.

<?php
	session_start();
	session_regenerate_id(true);
?>
<html>
<head>
	<title>WorldBank.dom session page</title>
</head>
<body>
<?php
	$timeout = 5 * 60;
	$curtime = (int)time();

	$maxSessionTime = 5 * 60 * 60; // 5 часа
	if(! isset($_SESSION['initial_time'])){
		$_SESSION['initial_time'] = (int)time();
	}
	if($curtime-$_SESSION['initial_time'] > $maxSessionTime){
		echo 'Maximum session time exceeded';
		session_destroy();
		return;
	}

	if (isset($_SESSION['last_active'])){
		if ($curtime-$_SESSION['last_active'] > $timeout){
			echo 'Session timeout';
			session_destroy();
			return;
		}
	}
	$_SESSION['last_active'] = $curtime;

	echo 'session id is: ';
	echo session_id();
	echo '<br>';
	if (!isset($_SESSION['counter'])){
		$_SESSION['counter'] = 0;
	}
	else{
		$_SESSION['counter']++;
	}
	echo 'counter: ';
	echo $_SESSION['counter'];
?>
</body></html>

Отново тествайте програмата, като намалите таймерите. Ще видите, че сесията ще приключи независимо, че се опитвате да я поддържате активна.

Задача: Възможно е атакуващият да "провали" нашите таймери чрез още друг вид атака - ако например успее да върне часовника на сървъра назад. В такъв случай сравненията от по-горните примери няма да функционират правилно. Помислете как може да защитим приложението срещу такъв exploit.

 



Добави коментар

Адресът на електронната поща няма да се публикува


*