diff --git a/PyMISP b/PyMISP index a2566f028..e20a9c753 160000 --- a/PyMISP +++ b/PyMISP @@ -1 +1 @@ -Subproject commit a2566f0282b9f3f83b7785e9fdac3f7aa95fd88b +Subproject commit e20a9c753957c2582789b85ca3176f27da089232 diff --git a/VERSION.json b/VERSION.json index 859814823..04b46f16c 100644 --- a/VERSION.json +++ b/VERSION.json @@ -1 +1 @@ -{"major":2, "minor":4, "hotfix":175} +{"major":2, "minor":4, "hotfix":176} diff --git a/app/Console/Command/TrainingShell.php b/app/Console/Command/TrainingShell.php index 4cee17115..a3b1fe37d 100644 --- a/app/Console/Command/TrainingShell.php +++ b/app/Console/Command/TrainingShell.php @@ -209,6 +209,11 @@ class TrainingShell extends AppShell { $this->createRemoteServersFromConfig($createdOrgs, $createdUsers); } + public function deleteAllSyncs() + { + $this->Server->deleteAll(['Server.id' > 0]); + } + private function __createOrgFromBlueprint($id) { $org = str_replace('$ID', $id, $this->__config['org_blueprint']); diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index 3550c0fec..715457783 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 = '155'; - public $pyMispVersion = '2.4.175'; + public $pyMispVersion = '2.4.176'; public $phpmin = '7.2'; public $phprec = '7.4'; public $phptoonew = '8.0'; @@ -962,6 +962,14 @@ class AppController extends Controller return $user; } + private function __captureParam($data, $param, $value) + { + if ($this->modelClass->checkParam($param)) { + $data[$param] = $value; + } + return $data; + } + /** * generic function to standardise on the collection of parameters. Accepts posted request objects, url params, named url params * @param array $options @@ -982,9 +990,21 @@ class AppController extends Controller return false; } else { if (isset($request->data['request'])) { - $data = array_merge($data, $request->data['request']); + $temp = $request->data['request']; } else { - $data = array_merge($data, $request->data); + $temp = $request->data; + } + if (empty($options['paramArray'])) { + foreach ($options['paramArray'] as $param => $value) { + $data = $this->__captureParam($data, $param, $value); + } + $data = array_merge($data, $temp); + } else { + foreach ($options['paramArray'] as $param) { + if (isset($temp[$param])) { + $data[$param] = $temp[$param]; + } + } } } } diff --git a/app/Controller/Component/IndexFilterComponent.php b/app/Controller/Component/IndexFilterComponent.php index 15fc73924..064a0bb87 100644 --- a/app/Controller/Component/IndexFilterComponent.php +++ b/app/Controller/Component/IndexFilterComponent.php @@ -54,7 +54,7 @@ class IndexFilterComponent extends Component private function __massageData($data, $request, $paramArray) { $data = array_filter($data, function($paramName) use ($paramArray) { - return in_array($paramName, $paramArray); + return in_array($paramName, $paramArray, true); }, ARRAY_FILTER_USE_KEY); if (!empty($paramArray)) { diff --git a/app/Controller/LogsController.php b/app/Controller/LogsController.php index b86db15cb..1d540ae48 100644 --- a/app/Controller/LogsController.php +++ b/app/Controller/LogsController.php @@ -285,6 +285,12 @@ class LogsController extends AppController $filters['model'] = $this->request->data['Log']['model']; $filters['model_id'] = $this->request->data['Log']['model_id']; $filters['title'] = $this->request->data['Log']['title']; + if (!empty ($this->request->data['Log']['from'])) { + $filters['from'] = $this->request->data['Log']['from']; + } + if (!empty ($this->request->data['Log']['to'])) { + $filters['to'] = $this->request->data['Log']['to']; + } $filters['change'] = $this->request->data['Log']['change']; if (Configure::read('MISP.log_client_ip')) { $filters['ip'] = $this->request->data['Log']['ip']; @@ -297,6 +303,8 @@ class LogsController extends AppController $this->set('modelSearch', $filters['model']); $this->set('model_idSearch', $filters['model_id']); $this->set('titleSearch', $filters['title']); + $this->set('fromSearch', $filters['from'] ?? null); + $this->set('toSearch', $filters['to'] ?? null); $this->set('changeSearch', $filters['change']); if (Configure::read('MISP.log_client_ip')) { $this->set('ipSearch', $filters['ip']); @@ -329,6 +337,8 @@ class LogsController extends AppController $this->Session->write('paginate_conditions_log_model_id', $filters['model_id']); $this->Session->write('paginate_conditions_log_title', $filters['title']); $this->Session->write('paginate_conditions_log_change', $filters['change']); + $this->Session->write('paginate_conditions_log_change', $filters['from'] ?? null); + $this->Session->write('paginate_conditions_log_change', $filters['to'] ?? null); if (Configure::read('MISP.log_client_ip')) { $this->Session->write('paginate_conditions_log_ip', $filters['ip']); } @@ -345,6 +355,8 @@ class LogsController extends AppController $filters['model_id'] = $this->Session->read('paginate_conditions_log_model_id'); $filters['title'] = $this->Session->read('paginate_conditions_log_title'); $filters['change'] = $this->Session->read('paginate_conditions_log_change'); + $filters['change'] = $this->Session->read('paginate_conditions_log_from') ?? null; + $filters['change'] = $this->Session->read('paginate_conditions_log_to') ?? null; if (Configure::read('MISP.log_client_ip')) { $filters['ip'] = $this->Session->read('paginate_conditions_log_ip'); } @@ -357,6 +369,8 @@ class LogsController extends AppController $this->set('model_idSearch', $filters['model_id']); $this->set('titleSearch', $filters['title']); $this->set('changeSearch', $filters['change']); + $this->set('changeSearch', $filters['from'] ?? null); + $this->set('changeSearch', $filters['to'] ?? null); if (Configure::read('MISP.log_client_ip')) { $this->set('ipSearch', $filters['ip']); } @@ -449,6 +463,12 @@ class LogsController extends AppController if (isset($filters['change']) && !empty($filters['change'])) { $conditions['LOWER(Log.change) LIKE'] = '%' . strtolower($filters['change']) . '%'; } + if (isset($filters['from']) && !empty($filters['from'])) { + $conditions['Log.created >='] = $filters['from']; + } + if (isset($filters['to']) && !empty($filters['to'])) { + $conditions['Log.created <='] = $filters['to']; + } if (Configure::read('MISP.log_client_ip') && isset($filters['ip']) && !empty($filters['ip'])) { $conditions['Log.ip LIKE'] = '%' . $filters['ip'] . '%'; } diff --git a/app/Controller/UsersController.php b/app/Controller/UsersController.php index 3aed0deae..597110166 100644 --- a/app/Controller/UsersController.php +++ b/app/Controller/UsersController.php @@ -301,6 +301,7 @@ class UsersController extends AppController // What fields should be saved (allowed to be saved) $user['User']['change_pw'] = 0; $user['User']['password'] = $this->request->data['User']['password']; + $user['User']['last_pw_change'] = time(); if ($this->_isRest()) { $user['User']['confirm_password'] = $this->request->data['User']['password']; } else { @@ -475,7 +476,8 @@ class UsersController extends AppController 'last_api_access', 'force_logout', 'date_created', - 'date_modified' + 'date_modified', + 'last_pw_change' ), 'contain' => array( 'Organisation' => array('id', 'name'), @@ -687,6 +689,7 @@ class UsersController extends AppController } } $this->request->data['User']['date_created'] = time(); + $this->request->data['User']['last_pw_change'] = $this->request->data['User']['date_created']; if (!array_key_exists($this->request->data['User']['role_id'], $syncRoles)) { $this->request->data['User']['server_id'] = 0; } @@ -758,7 +761,7 @@ class UsersController extends AppController $this->Flash->error(__('The user could not be saved. Invalid organisation.')); } } else { - $fieldList = array('password', 'email', 'external_auth_required', 'external_auth_key', 'enable_password', 'confirm_password', 'org_id', 'role_id', 'authkey', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'invited_by', 'change_pw', 'termsaccepted', 'newsread', 'date_created', 'date_modified'); + $fieldList = array('password', 'email', 'external_auth_required', 'external_auth_key', 'enable_password', 'confirm_password', 'org_id', 'role_id', 'authkey', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'invited_by', 'change_pw', 'termsaccepted', 'newsread', 'date_created', 'date_modified', 'last_pw_change'); if ($this->User->save($this->request->data, true, $fieldList)) { $notification_message = ''; if (!empty($this->request->data['User']['notify'])) { @@ -953,6 +956,8 @@ class UsersController extends AppController $this->__canChangePassword() ) { $fields[] = 'password'; + $fields[] = 'last_pw_change'; + $this->request->data['User']['last_pw_change'] = time(); if ($this->_isRest() && !isset($this->request->data['User']['confirm_password'])) { $this->request->data['User']['confirm_password'] = $this->request->data['User']['password']; $fields[] = 'confirm_password'; diff --git a/app/Model/AppModel.php b/app/Model/AppModel.php index 974c97828..b90001e90 100644 --- a/app/Model/AppModel.php +++ b/app/Model/AppModel.php @@ -85,7 +85,7 @@ class AppModel extends Model 93 => false, 94 => false, 95 => true, 96 => false, 97 => true, 98 => false, 99 => false, 100 => false, 101 => false, 102 => false, 103 => false, 104 => false, 105 => false, 106 => false, 107 => false, 108 => false, 109 => false, 110 => false, - 111 => false, 112 => false, 113 => true, 114 => false + 111 => false, 112 => false, 113 => true, 114 => false, 115 => false ); const ADVANCED_UPDATES_DESCRIPTION = array( @@ -1973,6 +1973,10 @@ class AppModel extends Model case 114: $indexArray[] = ['object_references', 'uuid']; break; + case 115: + $sqlArray[] = "ALTER TABLE `users` ADD COLUMN `last_pw_change` BIGINT(20) NULL DEFAULT NULL;"; + $sqlArray[] = "UPDATE `users` SET last_pw_change=date_modified WHERE last_pw_change IS NULL"; + break; case 'fixNonEmptySharingGroupID': $sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;'; $sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;'; @@ -3288,26 +3292,32 @@ class AppModel extends Model foreach ($filters as $f) { if ($f === -1) { foreach ($keys as $key) { - $temp['OR'][$key][] = -1; + if ($this->checkParam($key)) { + $temp['OR'][$key][] = -1; + } } continue; } // split the filter params into two lists, one for substring searches one for exact ones if (is_string($f) && ($f[strlen($f) - 1] === '%' || $f[0] === '%')) { foreach ($keys as $key) { - if ($operator === 'NOT') { - $temp[] = array($key . ' NOT LIKE' => $f); - } else { - $temp[] = array($key . ' LIKE' => $f); - $temp[] = array($key => $f); + if ($this->checkParam($key)) { + if ($operator === 'NOT') { + $temp[] = array($key . ' NOT LIKE' => $f); + } else { + $temp[] = array($key . ' LIKE' => $f); + $temp[] = array($key => $f); + } } } } else { foreach ($keys as $key) { - if ($operator === 'NOT') { - $temp[$key . ' !='][] = $f; - } else { - $temp['OR'][$key][] = $f; + if ($this->checkParam($key)) { + if ($operator === 'NOT') { + $temp[$key . ' !='][] = $f; + } else { + $temp['OR'][$key][] = $f; + } } } } @@ -4017,4 +4027,9 @@ class AppModel extends Model return false; } + + public function checkParam($param) + { + return preg_match('/^[\w\_\-\. ]+$/', $param); + } } diff --git a/app/Model/User.php b/app/Model/User.php index f2a5403fb..afbec075e 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -984,6 +984,7 @@ class User extends AppModel if ($result) { $this->id = $user['User']['id']; $this->saveField('password', $password); + $this->saveField('last_pw_change', time()); $this->updateField($user['User'], 'change_pw', 1); if ($simpleReturn) { return true; diff --git a/app/View/Elements/healthElements/diagnostics.ctp b/app/View/Elements/healthElements/diagnostics.ctp index 0ced5e5c9..948bd038a 100644 --- a/app/View/Elements/healthElements/diagnostics.ctp +++ b/app/View/Elements/healthElements/diagnostics.ctp @@ -94,15 +94,11 @@ $humanReadableFilesize = function ($bytes, $dec = 2) {
-+
- - You are using a MISP installation method that does not support or recommend using the MISP self-update, such as a Docker container. Please update using the appropriate update mechanism. -
-