Index: branches/5.0.x/core/kernel/session/session.php
===================================================================
diff -u -r12369 -r12399
--- branches/5.0.x/core/kernel/session/session.php (.../session.php) (revision 12369)
+++ branches/5.0.x/core/kernel/session/session.php (.../session.php) (revision 12399)
@@ -1,6 +1,6 @@
SessionTimeout = $new_timeout;
}
+ /**
+ * Calculates browser signature
+ *
+ * @return string
+ */
+ function _getBrowserSignature()
+ {
+ $signature_parts = Array(
+ 'HTTP_USER_AGENT', 'SERVER_PROTOCOL',
+ 'HTTP_ACCEPT_CHARSET', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE'
+ );
+
+ $ret = '';
+
+ foreach ($signature_parts as $signature_part) {
+ if (array_key_exists($signature_part, $_SERVER)) {
+ $ret .= '&|&' . $_SERVER[$signature_part];
+ }
+ }
+
+ return md5( substr($ret, 3) );
+ }
+
function StoreSession(&$session, $additional_fields = Array())
{
if (defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound($this->TableName)) {
@@ -118,7 +141,8 @@
$fields_hash = Array (
$this->IDField => $session->SID,
- $this->TimestampField => $session->Expiration
+ $this->TimestampField => $session->Expiration,
+ 'BrowserSignature' => $this->_getBrowserSignature(),
);
// default values + additional values + values set during this script run
@@ -152,16 +176,29 @@
function LocateSession($sid)
{
- $query = ' SELECT * FROM '.$this->TableName.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($sid);
- $result = $this->Conn->GetRow($query);
-
+ $sql = 'SELECT *
+ FROM ' . $this->TableName . '
+ WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($sid);
+ $result = $this->Conn->GetRow($sql);
+
if ($result === false) {
return false;
}
+ // perform security checks to ensure, that session is used by it's creator
+ if ($this->Application->ConfigValue('SessionBrowserSignatureCheck') && ($result['BrowserSignature'] != $this->_getBrowserSignature())) {
+ return false;
+ }
+
+ if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $_SERVER['REMOTE_ADDR'])) {
+ // most secure, except for cases where NAT (Network Address Translation)
+ // is used and two or more computers can have same IP address
+ return false;
+ }
+
$this->DirectVars = $result;
-
$this->Expiration = $result[$this->TimestampField];
+
return true;
}
@@ -569,26 +606,34 @@
}
}
+ /**
+ * This is redirect from https to http or via versa
+ *
+ * @return bool
+ */
function IsHTTPSRedirect()
{
- $http_referer = getArrayValue($_SERVER, 'HTTP_REFERER');
+ $http_referer = array_key_exists('HTTP_REFERER', $_SERVER) ? $_SERVER['HTTP_REFERER'] : false;
+
return (
( PROTOCOL == 'https://' && preg_match('#http:\/\/#', $http_referer) )
||
( PROTOCOL == 'http://' && preg_match('#https:\/\/#', $http_referer) )
);
}
- function CheckReferer($for_cookies=0)
+ /**
+ * Helper method for detecting cookie availability
+ *
+ * @return bool
+ */
+ function _checkCookieReferer()
{
- if (!$for_cookies) {
- if ( !$this->Application->ConfigValue('SessionReferrerCheck') || $_SERVER['REQUEST_METHOD'] != 'POST') {
- return true;
- }
- }
- $path = preg_replace('/admin[\/]{0,1}$/', '', $this->CookiePath); // removing /admin for compatability with in-portal (in-link/admin/add_link.php)
+ // removing /admin for compatability with in-portal (in-link/admin/add_link.php)
+ $path = preg_replace('/admin[\/]{0,1}$/', '', $this->CookiePath);
$reg = '#^'.preg_quote(PROTOCOL.ltrim($this->CookieDomain, '.').$path).'#';
- return preg_match($reg, getArrayValue($_SERVER, 'HTTP_REFERER') ) || (defined('IS_POPUP') && IS_POPUP);
+
+ return preg_match($reg, getArrayValue($_SERVER, 'HTTP_REFERER') );
}
function CheckIfCookiesAreOn()
@@ -612,7 +657,7 @@
if (!$cookies_on || $this->IsHTTPSRedirect()) {
//If referer is our server, but we don't have our cookies_on, it's definetly off
$is_install = defined('IS_INSTALL') && IS_INSTALL;
- if (!$is_install && $this->CheckReferer(1) && !$this->Application->GetVar('admin') && !$this->IsHTTPSRedirect()) {
+ if (!$is_install && $this->_checkCookieReferer() && !$this->Application->GetVar('admin') && !$this->IsHTTPSRedirect()) {
$this->CookiesEnabled = false;
}
else {
@@ -642,19 +687,14 @@
function Check()
{
- // we should check referer if cookies are disabled, and in combined mode
- // auto mode would detect cookies, get only mode would turn it off - so we would get here
- // and we don't care about referal in cookies only mode
+ // don't check referer here, because it doesn't provide any security option and can be easily falsified
+
+ $sid = $this->GetPassedSIDValue();
- if ( $this->Mode != smCOOKIES_ONLY && (!$this->CookiesEnabled || $this->Mode == smCOOKIES_AND_GET) ) {
- if (!$this->CheckReferer())
- return false;
+ if (empty($sid)) {
+ return false;
}
- $sid = $this->GetPassedSIDValue();
-
- if (empty($sid)) return false;
-
//try to load session by sid, if everything is fine
$result = $this->LoadSession($sid);
@@ -666,22 +706,24 @@
function LoadSession($sid)
{
if( $this->Storage->LocateSession($sid) ) {
- //if we have session with such SID - get its expiration
+ // if we have session with such SID - get its expiration
$this->Expiration = $this->Storage->GetExpiration();
- //If session has expired
+ // If session has expired
if ($this->Expiration < adodb_mktime()) {
$this->Destroy();
// when Destory methods calls SetSession inside and new session get created
return $this->SessionSet;
}
- //Otherwise it's ok
+ // Otherwise it's ok
return true;
}
- else //fake or deleted due to expiration SID
+ else {
+ // fake or deleted due to expiration SID
return false;
+ }
}
function GetPassedSIDValue($use_cache = 1)
@@ -973,18 +1015,20 @@
}
$this->Application->Debugger->dumpVars($session_data);
- // dump real keys
- $data_keys = array_keys($session_data);
- $optional_keys = array_keys($this->OptionalData);
- $real_keys = array_diff($data_keys, $optional_keys);
-
- if ($real_keys) {
- $ret = '';
- foreach ($real_keys as $real_key) {
- $ret .= '[' . $real_key . '] = [' . $session_data[$real_key] . ']
';
+ if (!$this->RecallVar('admin')) {
+ // dump real keys (only for front-end)
+ $data_keys = array_keys($session_data);
+ $optional_keys = array_keys($this->OptionalData);
+ $real_keys = array_diff($data_keys, $optional_keys);
+
+ if ($real_keys) {
+ $ret = '';
+ foreach ($real_keys as $real_key) {
+ $ret .= '[' . $real_key . '] = [' . $session_data[$real_key] . ']
';
+ }
+
+ $this->Application->Debugger->appendHTML('Real Keys:
' . $ret);
}
-
- $this->Application->Debugger->appendHTML('Real Keys:
' . $ret);
}
}