chg: [security] Disable resetting password when password change is disabled

pull/9690/head
Jakub Onderka 2024-04-19 23:22:15 +02:00
parent 79f6124bd2
commit d5ba5af530
3 changed files with 16 additions and 19 deletions

View File

@ -793,10 +793,10 @@ class ACLComponent extends Component
'downloadTerms' => array('*'), 'downloadTerms' => array('*'),
'edit' => array('self_management_enabled'), 'edit' => array('self_management_enabled'),
'email_otp' => array('otp_enabled'), 'email_otp' => array('otp_enabled'),
'forgot' => array('*'), 'forgot' => ['AND' => ['password_forgotten_enabled', 'password_change_enabled']],
'otp' => array('otp_enabled'), 'otp' => ['otp_enabled'],
'hotp' => array('otp_enabled'), 'hotp' => ['otp_enabled'],
'totp_new' => array('otp_enabled'), 'totp_new' => ['otp_enabled'],
'totp_delete' => ['AND' => ['perm_admin', 'otp_enabled']], 'totp_delete' => ['AND' => ['perm_admin', 'otp_enabled']],
'searchGpgKey' => array('*'), 'searchGpgKey' => array('*'),
'fetchGpgKey' => array('*'), 'fetchGpgKey' => array('*'),
@ -806,7 +806,7 @@ class ACLComponent extends Component
'logout' => array('*'), 'logout' => array('*'),
'logout401' => array('*'), 'logout401' => array('*'),
'notificationSettings' => ['*'], 'notificationSettings' => ['*'],
'password_reset' => array('*'), 'password_reset' => ['AND' => ['password_forgotten_enabled', 'password_change_enabled']],
'register' => array('*'), 'register' => array('*'),
'registrations' => array(), 'registrations' => array(),
'resetAllSyncAuthKeys' => array(), 'resetAllSyncAuthKeys' => array(),
@ -925,7 +925,13 @@ class ACLComponent extends Component
}; };
$this->dynamicChecks['otp_enabled'] = function (array $user) { $this->dynamicChecks['otp_enabled'] = function (array $user) {
if (Configure::read('Security.otp_disabled')) { if (Configure::read('Security.otp_disabled')) {
throw new ForbiddenException('OTP is disabled on this instance.'); throw new ForbiddenException('OTP has been disabled on this instance.');
}
return true;
};
$this->dynamicChecks['password_forgotten_enabled'] = function (array $user) {
if (empty(Configure::read('Security.allow_password_forgotten'))) {
throw new ForbiddenException('Password reset has been disabled on this instance.');
} }
return true; return true;
}; };

View File

@ -3187,10 +3187,6 @@ class UsersController extends AppController
public function forgot() public function forgot()
{ {
if (empty(Configure::read('Security.allow_password_forgotten'))) {
$this->Flash->error(__('This feature is disabled.'));
$this->redirect('/');
}
if (!empty($this->Auth->user()) && !$this->_isRest()) { if (!empty($this->Auth->user()) && !$this->_isRest()) {
$this->Flash->info(__('You are already logged in, no need to ask for a password reset. Log out first.')); $this->Flash->info(__('You are already logged in, no need to ask for a password reset. Log out first.'));
$this->redirect('/'); $this->redirect('/');
@ -3216,10 +3212,6 @@ class UsersController extends AppController
public function password_reset($token) public function password_reset($token)
{ {
if (empty(Configure::read('Security.allow_password_forgotten'))) {
$this->Flash->error(__('This feature is disabled.'));
$this->redirect('/');
}
$this->loadModel('Server'); $this->loadModel('Server');
$this->set('complexity', !empty(Configure::read('Security.password_policy_complexity')) ? Configure::read('Security.password_policy_complexity') : $this->Server->serverSettings['Security']['password_policy_complexity']['value']); $this->set('complexity', !empty(Configure::read('Security.password_policy_complexity')) ? Configure::read('Security.password_policy_complexity') : $this->Server->serverSettings['Security']['password_policy_complexity']['value']);
$this->set('length', !empty(Configure::read('Security.password_policy_length')) ? Configure::read('Security.password_policy_length') : $this->Server->serverSettings['Security']['password_policy_length']['value']); $this->set('length', !empty(Configure::read('Security.password_policy_length')) ? Configure::read('Security.password_policy_length') : $this->Server->serverSettings['Security']['password_policy_length']['value']);
@ -3236,7 +3228,7 @@ class UsersController extends AppController
$this->redirect('/'); $this->redirect('/');
} }
} }
if ($this->request->is('post') || $this->request->is('put')) { if ($this->request->is(['post', 'put'])) {
$abortPost = false; $abortPost = false;
return $this->__pw_change(['User' => $user], 'password_reset', $abortPost, $token, true); return $this->__pw_change(['User' => $user], 'password_reset', $abortPost, $token, true);
} }

View File

@ -2124,11 +2124,11 @@ class User extends AppModel
return true; return true;
} else { } else {
return $this->forgot($email); return $this->forgot($email, $ip);
} }
} }
public function forgot($email, $ip, $jobId = null) public function forgot($email, $ip)
{ {
$user = $this->find('first', [ $user = $this->find('first', [
'recursive' => -1, 'recursive' => -1,
@ -2140,9 +2140,8 @@ class User extends AppModel
if (empty($user)) { if (empty($user)) {
return false; return false;
} }
$redis = $this->setupRedis();
$token = RandomTool::random_str(true, 40, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); $token = RandomTool::random_str(true, 40, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
$redis->set('misp:forgot:' . $token, $user['User']['id'], ['nx', 'ex' => 600]); RedisTool::init()->set('misp:forgot:' . $token, $user['User']['id'], ['nx', 'ex' => 600]);
$baseurl = Configure::check('MISP.external_baseurl') ? Configure::read('MISP.external_baseurl') : Configure::read('MISP.baseurl'); $baseurl = Configure::check('MISP.external_baseurl') ? Configure::read('MISP.external_baseurl') : Configure::read('MISP.baseurl');
$body = __( $body = __(
"Dear MISP user,\n\nyou have requested a password reset on the MISP instance at %s. Click the link below to change your password.\n\n%s\n\nThe link above is only valid for 10 minutes, feel free to request a new one if it has expired.\n\nIf you haven't requested a password reset, reach out to your admin team and let them know that someone has attempted it in your stead.\n\nMake sure you keep the contents of this e-mail confidential, do NOT ever forward it as it contains a reset token that is equivalent of a password if acted upon. The IP used to trigger the request was: %s\n\nBest regards,\nYour MISP admin team", "Dear MISP user,\n\nyou have requested a password reset on the MISP instance at %s. Click the link below to change your password.\n\n%s\n\nThe link above is only valid for 10 minutes, feel free to request a new one if it has expired.\n\nIf you haven't requested a password reset, reach out to your admin team and let them know that someone has attempted it in your stead.\n\nMake sure you keep the contents of this e-mail confidential, do NOT ever forward it as it contains a reset token that is equivalent of a password if acted upon. The IP used to trigger the request was: %s\n\nBest regards,\nYour MISP admin team",