diff --git a/PyMISP b/PyMISP index cca5287b2..9a7adb2e0 160000 --- a/PyMISP +++ b/PyMISP @@ -1 +1 @@ -Subproject commit cca5287b2b11a1951789680c75e10636dde98add +Subproject commit 9a7adb2e0d60d2edee9f541db808652875bae20e diff --git a/README.md b/README.md index f7516f8bb..2a28375fb 100644 --- a/README.md +++ b/README.md @@ -108,16 +108,16 @@ License This software is licensed under [GNU Affero General Public License version 3](http://www.gnu.org/licenses/agpl-3.0.html) -* Copyright (C) 2012-2022 Christophe Vandeplas +* Copyright (C) 2012-2023 Christophe Vandeplas * Copyright (C) 2012 Belgian Defence * Copyright (C) 2012 NATO / NCIRC -* Copyright (C) 2013-2022 Andras Iklody -* Copyright (C) 2015-2022 CIRCL - Computer Incident Response Center Luxembourg +* Copyright (C) 2013-2023 Andras Iklody +* Copyright (C) 2015-2023 CIRCL - Computer Incident Response Center Luxembourg * Copyright (C) 2016 Andreas Ziegler -* Copyright (C) 2018-2022 Sami Mokaddem -* Copyright (C) 2018-2022 Christian Studer -* Copyright (C) 2015-2022 Alexandre Dulaunoy +* Copyright (C) 2018-2023 Sami Mokaddem +* Copyright (C) 2018-2023 Christian Studer +* Copyright (C) 2015-2023 Alexandre Dulaunoy * Copyright (C) 2018-2022 Steve Clement -* Copyright (C) 2020-2022 Jakub Onderka +* Copyright (C) 2020-2023 Jakub Onderka For more information, [the list of authors and contributors](AUTHORS) is available. diff --git a/VERSION.json b/VERSION.json index 7b36fa445..6e1915b14 100644 --- a/VERSION.json +++ b/VERSION.json @@ -1 +1 @@ -{"major":2, "minor":4, "hotfix":167} +{"major":2, "minor":4, "hotfix":168} diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index 4b0d81383..ccb8e2201 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -34,7 +34,7 @@ class AppController extends Controller public $helpers = array('OrgImg', 'FontAwesome', 'UserName'); private $__queryVersion = '147'; - public $pyMispVersion = '2.4.167'; + public $pyMispVersion = '2.4.168'; public $phpmin = '7.2'; public $phprec = '7.4'; public $phptoonew = '8.0'; @@ -152,20 +152,25 @@ class AppController extends Controller } $this->User = ClassRegistry::init('User'); - if ($this->Auth->user()) { - if ($this->User->checkForSessionDestruction($this->Auth->user('id'))) { - $this->Auth->logout(); - $this->Session->destroy(); - $message = __('User deauthenticated on administrator request. Please reauthenticate.'); - if ($this->_isRest()) { - throw new ForbiddenException($message); - } else { - $this->Flash->warning($message); - $this->_redirectToLogin(); - } - } + + if (!empty($this->request->params['named']['disable_background_processing'])) { + Configure::write('MISP.background_jobs', 0); } + Configure::write('CurrentController', $controller); + Configure::write('CurrentAction', $action); + $versionArray = $this->User->checkMISPVersion(); + $this->mispVersion = implode('.', $versionArray); + $this->Security->blackHoleCallback = 'blackHole'; + + // send users away that are using ancient versions of IE + // Make sure to update this if IE 20 comes out :) + if (isset($_SERVER['HTTP_USER_AGENT'])) { + if (preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT']) && !strpos($_SERVER['HTTP_USER_AGENT'], 'Opera')) { + throw new MethodNotAllowedException('You are using an unsecure and outdated version of IE, please download Google Chrome, Mozilla Firefox or update to a newer version of IE. If you are running IE9 or newer and still receive this error message, please make sure that you are not running your browser in compatibility mode. If you still have issues accessing the site, get in touch with your administration team at ' . Configure::read('MISP.contact')); + } + } + // For fresh installation (salt empty) generate a new salt if (!Configure::read('Security.salt')) { $this->User->Server->serverSettingsSaveValue('Security.salt', $this->User->generateRandomPassword(32)); @@ -176,6 +181,10 @@ class AppController extends Controller $this->User->Server->serverSettingsSaveValue('MISP.uuid', CakeText::uuid()); } + /** + * Authentication related activities + */ + // Check if Apache provides kerberos authentication data $authUserFields = $this->User->describeAuthFields(); $envvar = Configure::read('ApacheSecureAuth.apacheEnv'); @@ -191,22 +200,7 @@ class AppController extends Controller } else { $this->Auth->authenticate[AuthComponent::ALL]['userFields'] = $authUserFields; } - if (!empty($this->request->params['named']['disable_background_processing'])) { - Configure::write('MISP.background_jobs', 0); - } - Configure::write('CurrentController', $controller); - Configure::write('CurrentAction', $action); - $versionArray = $this->User->checkMISPVersion(); - $this->mispVersion = implode('.', $versionArray); - $this->Security->blackHoleCallback = 'blackHole'; - - // send users away that are using ancient versions of IE - // Make sure to update this if IE 20 comes out :) - if (isset($_SERVER['HTTP_USER_AGENT'])) { - if (preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT']) && !strpos($_SERVER['HTTP_USER_AGENT'], 'Opera')) { - throw new MethodNotAllowedException('You are using an unsecure and outdated version of IE, please download Google Chrome, Mozilla Firefox or update to a newer version of IE. If you are running IE9 or newer and still receive this error message, please make sure that you are not running your browser in compatibility mode. If you still have issues accessing the site, get in touch with your administration team at ' . Configure::read('MISP.contact')); - } - } + $userLoggedIn = false; if (Configure::read('Plugin.CustomAuth_enable')) { $userLoggedIn = $this->__customAuthentication($_SERVER); @@ -528,12 +522,24 @@ class AppController extends Controller } $this->Flash->info($message); $this->Auth->logout(); - throw new MethodNotAllowedException($message);//todo this should pb be removed? + $this->_redirectToLogin(); + return false; } else { $this->Flash->error(__('Warning: MISP is currently disabled for all users. Enable it in Server Settings (Administration -> Server Settings -> MISP tab -> live). An update might also be in progress, you can see the progress in ') , array('params' => array('url' => $this->baseurl . '/servers/updateProgress/', 'urlName' => __('Update Progress')), 'clear' => 1)); } } + // 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'])) { + $this->Auth->logout(); + $this->Session->destroy(); + $message = __('User deauthenticated on administrator request. Please reauthenticate.'); + $this->Flash->warning($message); + $this->_redirectToLogin(); + return false; + } + // Force logout doesn't make sense for API key authentication if (!$this->isApiAuthed && $user['force_logout']) { $this->User->id = $user['id']; diff --git a/app/Controller/AuditLogsController.php b/app/Controller/AuditLogsController.php index 24d4f709d..4199c748f 100644 --- a/app/Controller/AuditLogsController.php +++ b/app/Controller/AuditLogsController.php @@ -192,10 +192,13 @@ class AuditLogsController extends AppController $list[$k]['AuditLog']['action_human'] = $this->actions[$item['AuditLog']['action']]; } - $this->set('list', $list); + $this->set('data', $list); $this->set('event', $event); $this->set('mayModify', $this->__canModifyEvent($event)); - $this->set('title_for_layout', __('Audit logs for event #%s', $event['Event']['id'])); + $this->set('menuData', [ + 'menuList' => 'event', + 'menuItem' => 'eventLog' + ]); } public function fullChange($id) diff --git a/app/Controller/Component/ACLComponent.php b/app/Controller/Component/ACLComponent.php index c78f98c15..99390e34d 100644 --- a/app/Controller/Component/ACLComponent.php +++ b/app/Controller/Component/ACLComponent.php @@ -125,7 +125,7 @@ class ACLComponent extends Component 'decayingModel' => array( "update" => array(), "export" => array('*'), - "import" => array('*'), + "import" => array('OR' => array('perm_admin', 'perm_decaying')), "view" => array('*'), "index" => array('*'), "add" => array( 'OR' => array('perm_admin', 'perm_decaying')), diff --git a/app/Controller/Component/CRUDComponent.php b/app/Controller/Component/CRUDComponent.php index fb276e34d..81ad2bfb1 100644 --- a/app/Controller/Component/CRUDComponent.php +++ b/app/Controller/Component/CRUDComponent.php @@ -114,7 +114,7 @@ class CRUDComponent extends Component $this->Controller->Flash->success($message); if (!empty($params['displayOnSuccess'])) { $this->Controller->set('entity', $data); - $this->Controller->set('referer', $this->Controller->referer()); + $this->Controller->set('referer', $this->Controller->referer(['action' => 'view', $model->id], true)); $this->Controller->render($params['displayOnSuccess']); return; } diff --git a/app/Controller/ServersController.php b/app/Controller/ServersController.php index 2123522ec..9035853d2 100644 --- a/app/Controller/ServersController.php +++ b/app/Controller/ServersController.php @@ -1726,6 +1726,7 @@ class ServersController extends AppController if (!$server) { throw new NotFoundException(__('Invalid server')); } + @session_write_close(); // close session to allow concurrent requests $result = $this->Server->runConnectionTest($server); if ($result['status'] == 1) { if (isset($result['info']['version']) && preg_match('/^[0-9]+\.+[0-9]+\.[0-9]+$/', $result['info']['version'])) { diff --git a/app/Controller/ShadowAttributesController.php b/app/Controller/ShadowAttributesController.php index 48b448091..6ba08cbd1 100644 --- a/app/Controller/ShadowAttributesController.php +++ b/app/Controller/ShadowAttributesController.php @@ -62,8 +62,10 @@ class ShadowAttributesController extends AppController // If the old_id is set to anything but 0 then we're dealing with a proposed edit to an existing attribute if ($shadow['old_id'] != 0) { // Find the live attribute by the shadow attribute's uuid, so we can begin editing it - $this->Attribute->contain = 'Event'; - $activeAttribute = $this->Attribute->findByUuid($shadow['uuid']); + $activeAttribute = $this->Attribute->find('first', [ + 'conditions' => ['Attribute.uuid' => $shadow['uuid']], + 'contain' => ['Event'], + ]); // Send those away that shouldn't be able to edit this if (!$this->__canModifyEvent($activeAttribute)) { diff --git a/app/Controller/UsersController.php b/app/Controller/UsersController.php index 51ca9e6d2..08ab97cb0 100644 --- a/app/Controller/UsersController.php +++ b/app/Controller/UsersController.php @@ -1230,6 +1230,11 @@ class UsersController extends AppController $this->Bruteforce->insert($this->request->data['User']['email']); } } + + // + // Actions needed for the first access, when the database is not populated yet. + // + // populate the DB with the first role (site admin) if it's empty if (!$this->User->Role->hasAny()) { $siteAdmin = array('Role' => array( @@ -1279,7 +1284,6 @@ class UsersController extends AppController } $org_id = $this->User->Organisation->id; } - // populate the DB with the first user if it's empty if (!$this->User->hasAny()) { if (!isset($org_id)) { @@ -1291,7 +1295,6 @@ class UsersController extends AppController $org_id = $firstOrg['Organisation']['id']; } } - $this->User->runUpdates(); $this->User->createInitialUser($org_id); } @@ -1300,25 +1303,25 @@ class UsersController extends AppController private function _postlogin() { - $this->User->extralog($this->Auth->user(), "login"); - $this->User->Behaviors->disable('SysLogLogable.SysLogLogable'); - $this->User->id = $this->Auth->user('id'); - $user = $this->User->find('first', array( - 'conditions' => array( - 'User.id' => $this->Auth->user('id') - ), - 'recursive' => -1 - )); - unset($user['User']['password']); - $this->User->updateLoginTimes($user['User']); - $lastUserLogin = $user['User']['last_login']; - $this->User->Behaviors->enable('SysLogLogable.SysLogLogable'); - if ($lastUserLogin) { - $readableDatetime = (new DateTime())->setTimestamp($lastUserLogin)->format('D, d M y H:i:s O'); // RFC822 - $this->Flash->info(__('Welcome! Last login was on %s', $readableDatetime)); - } - // no state changes are ever done via GET requests, so it is safe to return to the original page: - $this->redirect($this->Auth->redirectUrl()); + $this->User->extralog($this->Auth->user(), "login"); + $this->User->Behaviors->disable('SysLogLogable.SysLogLogable'); + $this->User->id = $this->Auth->user('id'); + $user = $this->User->find('first', array( + 'conditions' => array( + 'User.id' => $this->Auth->user('id') + ), + 'recursive' => -1 + )); + unset($user['User']['password']); + $this->User->updateLoginTimes($user['User']); + $lastUserLogin = $user['User']['last_login']; + $this->User->Behaviors->enable('SysLogLogable.SysLogLogable'); + if ($lastUserLogin) { + $readableDatetime = (new DateTime())->setTimestamp($lastUserLogin)->format('D, d M y H:i:s O'); // RFC822 + $this->Flash->info(__('Welcome! Last login was on %s', $readableDatetime)); + } + // no state changes are ever done via GET requests, so it is safe to return to the original page: + $this->redirect($this->Auth->redirectUrl()); } public function routeafterlogin() diff --git a/app/View/AuditLogs/event_index.ctp b/app/View/AuditLogs/event_index.ctp index 9fd0aa7d4..b78afc18b 100644 --- a/app/View/AuditLogs/event_index.ctp +++ b/app/View/AuditLogs/event_index.ctp @@ -1,48 +1,59 @@ -
= $this->LightPaginator->sort('created') ?> | -= $this->LightPaginator->sort('user_id', __('User')) ?> | -= $this->LightPaginator->sort('org_id', __('Org')) ?> | -= $this->LightPaginator->sort('action') ?> | -= __('Model') ?> | -= __('Title') ?> | -= __('Change') ?> | -
---|---|---|---|---|---|---|
= $this->Time->time($item['AuditLog']['created']); ?> | -- | = isset($item['Organisation']) ? $this->OrgImg->getOrgLogo($item, 24) : '' ?> | -= h($item['AuditLog']['action_human']) ?> | -= h($item['AuditLog']['model']) . ' #' . intval($item['AuditLog']['model_id']) ?> | -= h($item['AuditLog']['title']) ?> | -= $this->element('AuditLog/change', ['item' => $item]) ?> | -
= h($entity['AuthKey']['authkey_raw']) ?>= __('Please make sure that you note down the auth key below, this is the only time the auth key is shown in plain text, so make sure you save it. If you lose the key, simply remove the entry and generate a new one.'); ?>
=__('MISP will use the first and the last 4 characters for identification purposes.')?>
= h($entity['AuthKey']['authkey_raw']) ?>- = __('I have noted down my key, take me back now') ?> + = __('I have noted down my key, take me back now') ?> diff --git a/app/View/Elements/genericElements/IndexTable/Fields/custom_element.ctp b/app/View/Elements/genericElements/IndexTable/Fields/custom_element.ctp new file mode 100644 index 000000000..b661e6bda --- /dev/null +++ b/app/View/Elements/genericElements/IndexTable/Fields/custom_element.ctp @@ -0,0 +1 @@ += $this->element($field['element_path'], ['item' => $row]) ?> \ No newline at end of file diff --git a/app/View/Elements/genericElements/IndexTable/Fields/generic_field.ctp b/app/View/Elements/genericElements/IndexTable/Fields/generic_field.ctp index 0d63cdc3f..2698be658 100644 --- a/app/View/Elements/genericElements/IndexTable/Fields/generic_field.ctp +++ b/app/View/Elements/genericElements/IndexTable/Fields/generic_field.ctp @@ -1,5 +1,8 @@ 1) { $implodeGlue = isset($field['array_implode_glue']) ? $field['array_implode_glue'] : ', '; diff --git a/app/View/Elements/genericElements/IndexTable/Fields/model.ctp b/app/View/Elements/genericElements/IndexTable/Fields/model.ctp new file mode 100644 index 000000000..52d0eaeda --- /dev/null +++ b/app/View/Elements/genericElements/IndexTable/Fields/model.ctp @@ -0,0 +1,3 @@ +Time->time($time); \ No newline at end of file diff --git a/app/View/Feeds/add.ctp b/app/View/Feeds/add.ctp index 47ccdefbd..dc49d38a2 100755 --- a/app/View/Feeds/add.ctp +++ b/app/View/Feeds/add.ctp @@ -73,7 +73,7 @@ echo $this->element('genericElements/Form/genericForm', [ 'field' => 'orgc_id', 'label' => __('Creator organisation'), 'options' => $dropdownData['orgs'], - 'value' => $this->request->params['action'] === 'add' ? $me['org_id'] : '', + 'value' => $this->request->params['action'] === 'add' ? $me['org_id'] : null, 'type' => 'dropdown', 'div' => ['id' => 'OrgcDiv', 'style' => 'display:none', 'class' => 'optionalField'], 'class' => 'form-control span6' diff --git a/app/View/Logs/event_index.ctp b/app/View/Logs/event_index.ctp index 7f38ecdeb..d53dec313 100644 --- a/app/View/Logs/event_index.ctp +++ b/app/View/Logs/event_index.ctp @@ -1,22 +1,24 @@
= __('Showing log entries for data currently stored in the database. Entries about hard-deleted data have been omitted.') ?>
Paginator->sort('org');?> | -Paginator->sort('email');?> | -Paginator->sort('action');?> | -Paginator->sort('model');?> | -Paginator->sort('title');?> | -Paginator->sort('created');?> | +LightPaginator->sort('org');?> | +LightPaginator->sort('email');?> | +LightPaginator->sort('action');?> | +LightPaginator->sort('model');?> | +LightPaginator->sort('title');?> | +LightPaginator->sort('created');?> |
---|---|---|---|---|---|---|---|---|---|---|---|
Paginator->counter(array( + echo $this->LightPaginator->counter(array( 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}') )); ?> @@ -47,9 +49,9 @@