Revert "Trust PHP session and remove remember me cookie" (#5252)

This commit is contained in:
Neil Lathwood
2016-12-27 20:37:03 +00:00
committed by GitHub
parent 3b198243d5
commit f5ce3c509a
5 changed files with 57 additions and 154 deletions

View File

@@ -1,17 +1,9 @@
<?php <?php
require_once 'includes/authentication_functions.inc.php';
@ini_set('session.use_only_cookies', 1); @ini_set('session.use_only_cookies', 1);
@ini_set('session.cookie_httponly', 1); @ini_set('session.cookie_httponly', 1);
@ini_set('session.use_strict_mode', 1); // php >= 5.5.2
@ini_set('session.use_trans_sid', 0); // insecure feature, be sure it is disabled
/* make sure our PHP sessions can survive for the desired amount of time */ session_start();
@ini_set('session.gc_maxlifetime', $config['auth_remember'] * 60 * 60 * 24);
auth_check_session();
// Preflight checks // Preflight checks
if (!is_dir($config['rrd_dir'])) { if (!is_dir($config['rrd_dir'])) {
@@ -31,103 +23,87 @@ dbDelete('session', '`session_expiry` < ?', array(time()));
if ($vars['page'] == 'logout' && $_SESSION['authenticated']) { if ($vars['page'] == 'logout' && $_SESSION['authenticated']) {
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged Out'), 'authlog'); dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged Out'), 'authlog');
auth_end_session(); dbDelete('session', '`session_username` = ? AND session_value = ?', array($_SESSION['username'], $_COOKIE['sess_id']));
unset($_SESSION);
unset($_COOKIE);
setcookie('sess_id', '', (time() - 60 * 60 * 24 * $config['auth_remember']), '/');
setcookie('token', '', (time() - 60 * 60 * 24 * $config['auth_remember']), '/');
setcookie('auth', '', (time() - 60 * 60 * 24 * $config['auth_remember']), '/');
session_destroy();
$auth_message = 'Logged Out'; $auth_message = 'Logged Out';
header('Location: ' . $config['base_url']); header('Location: ' . $config['base_url']);
exit; exit;
} }
unset($form_password);
unset($form_username);
// We are only interested in login details passed via POST. // We are only interested in login details passed via POST.
if (isset($_POST['username']) && isset($_POST['password'])) { if (isset($_POST['username']) && isset($_POST['password'])) {
$form_username = clean($_POST['username']); $_SESSION['username'] = clean($_POST['username']);
$form_password = $_POST['password']; $_SESSION['password'] = $_POST['password'];
} elseif (isset($_GET['username']) && isset($_GET['password'])) { } elseif (isset($_GET['username']) && isset($_GET['password'])) {
/* FIXME: allowing GET for authentication reduces security */ $_SESSION['username'] = clean($_GET['username']);
$form_username = clean($_GET['username']); $_SESSION['password'] = $_GET['password'];
$form_password = $_GET['password'];
} elseif (isset($_SERVER['REMOTE_USER'])) { } elseif (isset($_SERVER['REMOTE_USER'])) {
$form_username = clean($_SERVER['REMOTE_USER']); $_SESSION['username'] = $_SERVER['REMOTE_USER'];
} }
if (!isset($config['auth_mechanism'])) { if (!isset($config['auth_mechanism'])) {
$config['auth_mechanism'] = 'mysql'; $config['auth_mechanism'] = 'mysql';
} }
if (!$_SESSION['authenticated']) { $auth_success = 0;
$auth_mechanism_successful = false;
if (isset($form_username)) { if ((isset($_SESSION['username'])) || (isset($_COOKIE['sess_id'],$_COOKIE['token']))) {
/* try password auth */ if (reauthenticate($_COOKIE['sess_id'], $_COOKIE['token']) || authenticate($_SESSION['username'], $_SESSION['password'])) {
$_SESSION['username'] = $form_username;
$auth_mechanism_successful = authenticate($form_username, $form_password);
if ($auth_mechanism_successful !== 1) {
$auth_mechanism_successful = false;
}
if (isset($_SESSION['username']) && $_SESSION['username'] !== $form_username) {
/* Must be using one of the auth methods that trusts $_SERVER['REMOTE_USER'] */
$form_username = $_SESSION['username'];
}
}
if ($auth_mechanism_successful === 1) {
if ($config['twofactor'] === true && !isset($_SESSION['twofactor'])) {
include_once $config['install_dir'].'/html/includes/authentication/twofactor.lib.php';
twofactor_auth();
}
if (!$config['twofactor'] || $_SESSION['twofactor']) {
/* Congratulations, you are authenticated! */
/* do this before changing the session_id so the session cookie has
* the right lifetime; a long expiration time on an unauthenticated
* session should not be dangerous */
if (isset($_POST['remember'])) {
// keep session cookie for auth_remember days
session_set_cookie_params($config['auth_remember'] * 60 * 60 * 24);
$_SESSION['expires'] = time() + $config['auth_remember'] * 60 * 60 * 24;
} else {
// keep session cookie for the duration of the browser session
session_set_cookie_params(0);
// valid for auth_no_remember minutes, regardless of activity
$_SESSION['expires'] = time() + $config['auth_no_remember'] * 60;
}
/* prevent session fixation vulnerabilities */
auth_update_session_id();
$_SESSION['authenticated'] = true;
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged In'), 'authlog');
}
}
if ($_SESSION['authenticated']) {
if (!$_SESSION['username']) {
unset($_SESSION['authenticated']);
print_error("ERROR: auth_mechanism did not set session username");
exit();
}
$_SESSION['userlevel'] = get_userlevel($_SESSION['username']); $_SESSION['userlevel'] = get_userlevel($_SESSION['username']);
$_SESSION['user_id'] = get_userid($_SESSION['username']); $_SESSION['user_id'] = get_userid($_SESSION['username']);
if (!$_SESSION['authenticated']) {
if ($config['twofactor'] === true && !isset($_SESSION['twofactor'])) {
include_once $config['install_dir'].'/html/includes/authentication/twofactor.lib.php';
twofactor_auth();
}
if (!$config['twofactor'] || $_SESSION['twofactor']) {
$_SESSION['authenticated'] = true;
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged In'), 'authlog');
}
}
if (isset($_POST['remember'])) {
$sess_id = session_id();
$hasher = new PasswordHash(8, false);
$token = strgen();
$auth = strgen();
$hasher = new PasswordHash(8, false);
$token_id = $_SESSION['username'].'|'.$hasher->HashPassword($_SESSION['username'].$token);
// If we have been asked to remember the user then set the relevant cookies and create a session in the DB.
setcookie('sess_id', $sess_id, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
setcookie('token', $token_id, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
setcookie('auth', $auth, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
dbInsert(array('session_username' => $_SESSION['username'], 'session_value' => $sess_id, 'session_token' => $token, 'session_auth' => $auth, 'session_expiry' => time() + 60 * 60 * 24 * $config['auth_remember']), 'session');
}
if (isset($_COOKIE['sess_id'],$_COOKIE['token'],$_COOKIE['auth'])) {
// If we have the remember me cookies set then update session expiry times to keep us logged in.
$sess_id = session_id();
dbUpdate(array('session_value' => $sess_id, 'session_expiry' => time() + 60 * 60 * 24 * $config['auth_remember']), 'session', 'session_auth=?', array($_COOKIE['auth']));
setcookie('sess_id', $sess_id, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
setcookie('token', $_COOKIE['token'], (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
setcookie('auth', $_COOKIE['auth'], (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
}
$permissions = permissions_cache($_SESSION['user_id']); $permissions = permissions_cache($_SESSION['user_id']);
if ($auth_mechanism_successful === 1) { if (isset($_POST['username'])) {
header('Location: '.$_SERVER['REQUEST_URI'], true, 303); header('Location: '.$_SERVER['REQUEST_URI'], true, 303);
exit; exit;
} }
} elseif (isset($form_username) || isset($_SESSION['username'])) { } elseif (isset($_SESSION['username'])) {
global $auth_error; global $auth_error;
if (isset($auth_error)) { if (isset($auth_error)) {
$auth_message = $auth_error; $auth_message = $auth_error;
} else { } else {
$auth_message = 'Authentication Failed'; $auth_message = 'Authentication Failed';
} }
auth_end_session(); unset($_SESSION['authenticated']);
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Authentication Failure'), 'authlog'); dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Authentication Failure'), 'authlog');
} }
} else {
/* we have a valid, previously-authenticated session */
} }

View File

@@ -110,7 +110,7 @@ function adduser($username, $level = 0, $email = '', $realname = '', $can_modify
{ {
// Check to see if user is already added in the database // Check to see if user is already added in the database
if (!user_exists_in_db($username)) { if (!user_exists_in_db($username)) {
$userid = dbInsert(array('username' => $username, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'twofactor' => $twofactor), 'users'); $userid = dbInsert(array('username' => $username, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'twofactor' => $twofactor, 'user_id' => get_userid($username)), 'users');
if ($userid == false) { if ($userid == false) {
return false; return false;
} else { } else {

View File

@@ -86,7 +86,7 @@ function adduser($username, $level = 0, $email = '', $realname = '', $can_modify
{ {
// Check to see if user is already added in the database // Check to see if user is already added in the database
if (!user_exists_in_db($username)) { if (!user_exists_in_db($username)) {
$userid = dbInsert(array('username' => $username, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'twofactor' => $twofactor), 'users'); $userid = dbInsert(array('username' => $username, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'twofactor' => $twofactor, 'user_id' => get_userid($username)), 'users');
if ($userid == false) { if ($userid == false) {
return false; return false;
} else { } else {

View File

@@ -1,68 +0,0 @@
<?php
/* Authentication-related functions */
function auth_end_session()
{
global $config;
/* delete the important things just in case, then blow this session away */
unset($_SESSION['authenticated']);
unset($_SESSION['user_id']);
unset($_SESSION['username']);
unset($_SESSION['userlevel']);
/* out with the old */
session_unset();
session_destroy();
/* in with the new */
session_start();
auth_update_session_id();
$_SESSION['last_activity'] = time();
$_SESSION['expires'] = time() + $config['auth_unauthenticated_session_timeout']*60;
}
function auth_check_session()
{
global $config;
session_start();
if (!isset($_SESSION['expires']) || !isset($_SESSION['last_activity'])) {
auth_end_session();
return;
}
// Check to see if the session has exceeded its maximum lifetime
if ($_SESSION['expires'] < time()) {
if ($_SESSION['authenticated']) {
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Session exceeded maximum lifetime'), 'authlog');
}
auth_end_session();
return;
}
if ($config['auth_idle_session_timeout'] > 0
&& $_SESSION['last_activity'] < time() + 60 * $config['auth_idle_session_timeout']) {
if ($_SESSION['authenticated']) {
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Session idle timeout'), 'authlog');
}
auth_end_session();
return;
}
}
function auth_update_session_id()
{
/* Change our session ID to help prevent session fixation attacs.
*/
/* The docs for session_regenerate_id claim that it can lose a session with
* an unreliable network connection, but this is only called during the
* login process, and the old session is useless anyway -- so we just
* blindly delete the old session and hope for the best
*/
session_regenerate_id(true);
}

View File

@@ -558,13 +558,8 @@ $config['allow_unauth_graphs_cidr'] = array();
// Allow graphs to be viewed without authorisation from certain IP ranges // Allow graphs to be viewed without authorisation from certain IP ranges
$config['auth_mechanism'] = 'mysql'; $config['auth_mechanism'] = 'mysql';
// Available mechanisms: mysql (default), ldap, http-auth // Available mechanisms: mysql (default), ldap, http-auth
$config['auth_remember'] = '30'; // days $config['auth_remember'] = '30';
// This is how long in days to remember users who select 'remember me' // This is how long in days to remember users who select remember me
$config['auth_no_remember'] = 60*4; // minutes, maximum session life without 'remember me' checked
$config['auth_idle_session_timeout'] = 0; // minutes or 0 to disable; sessions inactive this long will be invalidated
$config['auth_unauthenticated_session_timeout'] = 60; // minutes before expiring unauthenticated sessions
// LDAP Authentication // LDAP Authentication
$config['auth_ldap_version'] = 3; $config['auth_ldap_version'] = 3;
// v2 or v3 // v2 or v3