Merge pull request #9476 from JakubOnderka/session-destroy

fix: [internal] Session destroy
pull/9477/head
Jakub Onderka 2024-01-04 16:27:00 +01:00 committed by GitHub
commit 160ec13aee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 43 deletions

View File

@ -101,9 +101,7 @@ class AppController extends Controller
{
$controller = $this->request->params['controller'];
$action = $this->request->params['action'];
if (empty($this->Session->read('creation_timestamp'))) {
$this->Session->write('creation_timestamp', time());
}
if (Configure::read('MISP.system_setting_db')) {
App::uses('SystemSetting', 'Model');
SystemSetting::setGlobalSetting();
@ -544,13 +542,18 @@ class AppController extends Controller
}
}
$sessionCreationTime = $this->Session->read('creation_timestamp');
if (empty($sessionCreationTime)) {
$sessionCreationTime = $_SERVER['REQUEST_TIME'] ?? time();
$this->Session->write('creation_timestamp', $sessionCreationTime);
}
// kill existing sessions for a user if the admin/instance decides so
// exclude API authentication as it doesn't make sense
if (!$this->isApiAuthed && $this->User->checkForSessionDestruction($user['id'])) {
if (!$this->isApiAuthed && $this->User->checkForSessionDestruction($user['id'], $sessionCreationTime)) {
$this->Auth->logout();
$this->Session->destroy();
$message = __('User deauthenticated on administrator request. Please reauthenticate.');
$this->Flash->warning($message);
$this->Flash->warning(__('User deauthenticated on administrator request. Please reauthenticate.'));
$this->_redirectToLogin();
return false;
}

View File

@ -3096,41 +3096,41 @@ class UsersController extends AppController
}
}
if (!empty($conditions)) {
$user_ids = $this->User->find('list', [
$userIds = $this->User->find('list', [
'recursive' => -1,
'fields' => ['email', 'id'],
'conditions' => $conditions
]);
} else {
$user_ids = [__('Every user') => 'all'];
$userIds = [__('Every user') => 'all'];
}
if ($this->request->is('post')) {
$redis = RedisTool::init();
$kill_before = time();
foreach (array_values($user_ids) as $user_id) {
$redis->set('misp:session_destroy:' . $user_id, $kill_before);
$killBefore = time();
foreach ($userIds as $userId) {
$redis->set('misp:session_destroy:' . $userId, $killBefore);
}
$message = __(
'Session destruction cutoff set to the current timestamp for the given selection (%s). Session(s) will be destroyed on the next user interaction.',
implode(', ', array_keys($user_ids))
implode(', ', array_keys($userIds))
);
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('User', 'admin_destroy', false, $this->response->type(), $message);
return $this->RestResponse->successResponse(null, $message);
}
$this->Flash->success($message);
$this->redirect($this->referer());
} else {
$this->set(
'question',
__(
'Do you really wish to destroy the session for: %s ? The session destruction will occur when the users try to interact with MISP the next time.',
implode(', ', array_keys($user_ids))
)
);
$this->set('title', __('Destroy sessions'));
$this->set('actionName', 'Destroy');
$this->render('/genericTemplates/confirm');
}
$this->set(
'question',
__(
'Do you really wish to destroy the session for: %s? The session destruction will occur when the users try to interact with MISP the next time.',
implode(', ', array_keys($userIds))
)
);
$this->set('title', __('Destroy sessions'));
$this->set('actionName', 'Destroy');
$this->render('/genericTemplates/confirm');
}
public function view_login_history($user_id = null) {

View File

@ -2049,29 +2049,36 @@ class User extends AppModel
return $users;
}
public function checkForSessionDestruction($id)
/**
* @param int $id
* @param int $sessionCreationTimestamp
* @return bool
* @throws RedisException
*/
public function checkForSessionDestruction($id, $sessionCreationTimestamp)
{
if (empty(CakeSession::read('creation_timestamp'))) {
try {
$redis = RedisTool::init();
} catch (Exception $e) {
return false;
}
$redis = $this->setupRedis();
if ($redis) {
$cutoff = $redis->get('misp:session_destroy:' . $id);
$allcutoff = $redis->get('misp:session_destroy:all');
if (
empty($cutoff) ||
(
!empty($cutoff) &&
!empty($allcutoff) &&
$allcutoff < $cutoff
)
) {
$cutoff = $allcutoff;
}
if ($cutoff && CakeSession::read('creation_timestamp') < $cutoff) {
return true;
}
$cutoff = $redis->get('misp:session_destroy:' . $id);
$allcutoff = $redis->get('misp:session_destroy:all');
if (
empty($cutoff) ||
(
!empty($cutoff) &&
!empty($allcutoff) &&
$allcutoff < $cutoff
)
) {
$cutoff = $allcutoff;
}
if ($cutoff && $sessionCreationTimestamp < $cutoff) {
return true;
}
return false;
}