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);
}
}
Index: branches/5.0.x/core/install/install_schema.sql
===================================================================
diff -u -r12264 -r12399
--- branches/5.0.x/core/install/install_schema.sql (.../install_schema.sql) (revision 12264)
+++ branches/5.0.x/core/install/install_schema.sql (.../install_schema.sql) (revision 12399)
@@ -320,21 +320,21 @@
);
CREATE TABLE UserSession (
- SessionKey int(10) unsigned NOT NULL default '0',
- CurrentTempKey int(10) unsigned default NULL,
- PrevTempKey int(10) unsigned default NULL,
- LastAccessed int(10) unsigned NOT NULL default '0',
- PortalUserId int(11) NOT NULL default '-2',
- `Language` int(11) NOT NULL default '1',
- Theme int(11) NOT NULL default '1',
- GroupId int(11) NOT NULL default '0',
- IpAddress varchar(20) NOT NULL default '0.0.0.0',
- `Status` int(11) NOT NULL default '1',
- GroupList varchar(255) default NULL,
- tz int(11) default NULL,
- PRIMARY KEY (SessionKey),
+ SessionKey int(10) unsigned NOT NULL DEFAULT '0',
+ LastAccessed int(10) unsigned NOT NULL DEFAULT '0',
+ PortalUserId int(11) NOT NULL DEFAULT '-2',
+ `Language` int(11) NOT NULL DEFAULT '1',
+ Theme int(11) NOT NULL DEFAULT '1',
+ GroupId int(11) NOT NULL DEFAULT '0',
+ IpAddress varchar(20) NOT NULL DEFAULT '0.0.0.0',
+ `Status` int(11) NOT NULL DEFAULT '1',
+ GroupList varchar(255) DEFAULT NULL,
+ tz int(11) DEFAULT NULL,
+ BrowserSignature varchar(32) NOT NULL,
+ PRIMARY KEY (SessionKey),
KEY UserId (PortalUserId),
- KEY LastAccessed (LastAccessed)
+ KEY LastAccessed (LastAccessed),
+ KEY BrowserSignature (BrowserSignature)
);
CREATE TABLE EmailLog (
Index: branches/5.0.x/core/kernel/utility/unit_config_reader.php
===================================================================
diff -u -r12366 -r12399
--- branches/5.0.x/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 12366)
+++ branches/5.0.x/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 12399)
@@ -1,6 +1,6 @@
UmVxdWlyZSBTU0wgZm9yIGxvZ2luICYgY2hlY2tvdXQ=
RnJhbWVzIGluIGFkbWluaXN0cmF0aXZlIGNvbnNvbGUgYXJlIHJlc2l6YWJsZQ==
TWluaW1hbCBTZWFyY2ggS2V5d29yZCBMZW5ndGg=
+ U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBCcm93c2VyIFNpZ25hdHVyZQ==
+ U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBJUA==
V2Vic2l0ZSBTdWJ0aXRsZQ==
VGltZSB6b25lIG9mIHRoZSBzaXRl
U1NMIEZ1bGwgVVJMIChodHRwczovL3d3dy5kb21haW4uY29tL3BhdGgp
@@ -1070,7 +1072,6 @@
KE1pbmltdW0gMSk=
V2FybmluZyE=
V2VpZ2h0
- U2Vzc2lvbiBSZWZlcnJlciBDaGVja2luZw==
U2luZ2xlLVF1b3RlcyAoaWUuICcp
UmVjaXByb2NhbA==
UmVjb3Jkcw==
Index: branches/5.0.x/core/kernel/session/inp_session.php
===================================================================
diff -u -r12369 -r12399
--- branches/5.0.x/core/kernel/session/inp_session.php (.../inp_session.php) (revision 12369)
+++ branches/5.0.x/core/kernel/session/inp_session.php (.../inp_session.php) (revision 12399)
@@ -1,6 +1,6 @@
$this->Application->IsAdmin() ? 0 : -2, // Guest
'Language' => $this->Application->GetDefaultLanguageId(),
'Theme' => $this->Application->GetDefaultThemeId(),
- 'IpAddress' => $_SERVER['REMOTE_ADDR'],
+ 'IpAddress' => $_SERVER['REMOTE_ADDR'], // getenv('REMOTE_ADDR') won't work on IIS, so use $_SERVER instead
'GroupId' => $this->Application->ConfigValue('User_GuestGroup'),
'GroupList' => $this->Application->ConfigValue('User_GuestGroup'),
- 'CurrentTempKey'=> $session->SID,
);
parent::StoreSession($session, $fields_hash);
Index: branches/5.0.x/core/install/install_data.sql
===================================================================
diff -u -r12366 -r12399
--- branches/5.0.x/core/install/install_data.sql (.../install_data.sql) (revision 12366)
+++ branches/5.0.x/core/install/install_data.sql (.../install_data.sql) (revision 12399)
@@ -80,9 +80,11 @@
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'SessionCookieName', 'sid', 'In-Portal', 'in-portal:configure_advanced');
INSERT INTO ConfigurationAdmin VALUES ('KeepSessionOnBrowserClose', 'la_section_SettingsSession', 'la_config_KeepSessionOnBrowserClose', 'checkbox', '', '', 20.03, 0, 0);
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'KeepSessionOnBrowserClose', '0', 'In-Portal', 'in-portal:configure_advanced');
-INSERT INTO ConfigurationAdmin VALUES ('SessionReferrerCheck', 'la_section_SettingsSession', 'la_promt_ReferrerCheck', 'checkbox', NULL, NULL, 20.04, 0, 1);
-INSERT INTO ConfigurationValues VALUES (DEFAULT, 'SessionReferrerCheck', '1', 'In-Portal', 'in-portal:configure_advanced');
-INSERT INTO ConfigurationAdmin VALUES ('UseJSRedirect', 'la_section_SettingsSession', 'la_config_use_js_redirect', 'checkbox', '', '', 20.05, 0, 0);
+INSERT INTO ConfigurationAdmin VALUES ('SessionBrowserSignatureCheck', 'la_section_SettingsSession', 'la_config_SessionBrowserSignatureCheck', 'checkbox', NULL, NULL, 20.04, 0, 1);
+INSERT INTO ConfigurationValues VALUES (DEFAULT, 'SessionBrowserSignatureCheck', '0', 'In-Portal', 'in-portal:configure_advanced');
+INSERT INTO ConfigurationAdmin VALUES ('SessionIPAddressCheck', 'la_section_SettingsSession', 'la_config_SessionIPAddressCheck', 'checkbox', NULL, NULL, 20.05, 0, 1);
+INSERT INTO ConfigurationValues VALUES (DEFAULT, 'SessionIPAddressCheck', '0', 'In-Portal', 'in-portal:configure_advanced');
+INSERT INTO ConfigurationAdmin VALUES ('UseJSRedirect', 'la_section_SettingsSession', 'la_config_use_js_redirect', 'checkbox', '', '', 20.06, 0, 0);
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'UseJSRedirect', '0', 'In-Portal', 'in-portal:configure_advanced');
INSERT INTO ConfigurationAdmin VALUES ('SSL_URL', 'la_section_SettingsSSL', 'la_config_ssl_url', 'text', '', '', 30.01, 0, 1);
INSERT INTO ConfigurationValues VALUES (DEFAULT, 'SSL_URL', '', 'In-Portal', 'in-portal:configure_advanced');