Skip to content

Commit 36b43f1

Browse files
committed
fix: [security] Org admins could reset credentials for site admins
- org admins have the inherent ability to reset passwords for all of their org's users - this however could be abused if for some reason the host org of an instance would create org admins - the org admin could set a password manually for the site admin or simply use the API key of the site admin to impersonate them - the potential for abuse is very circumstancial as it requires the host org to create lower privilege org admins instead of the usual site admins - only org admins of the same organisation as the site admin could abuse this - as reported by Raymond Schippers
1 parent 90f4f03 commit 36b43f1

File tree

3 files changed

+60
-10
lines changed

3 files changed

+60
-10
lines changed

Diff for: app/Controller/LogsController.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,11 @@ public function admin_search($new = false)
343343
'conditions' => $conditions,
344344
'order' => array('Log.id' => 'DESC')
345345
);
346-
$this->set('list', $this->paginate());
346+
$list = $this->paginate();
347+
if (empty($this->Auth->user('Role')['perm_site_admin'])) {
348+
$list = $this->Log->filterSiteAdminSensitiveLogs($list);
349+
}
350+
$this->set('list', $list);
347351

348352
// and store into session
349353
$this->Session->write('paginate_conditions_log', $this->paginate);
@@ -394,7 +398,11 @@ public function admin_search($new = false)
394398
}
395399
$conditions = $this->__buildSearchConditions($filters);
396400
$this->paginate['conditions'] = $conditions;
397-
$this->set('list', $this->paginate());
401+
$list = $this->paginate();
402+
if (empty($this->Auth->user('Role')['perm_site_admin'])) {
403+
$list = $this->Log->filterSiteAdminSensitiveLogs($list);
404+
}
405+
$this->set('list', $list);
398406

399407
// set the same view as the index page
400408
$this->render('admin_index');

Diff for: app/Controller/UsersController.php

+23-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class UsersController extends AppController
1919
),
2020
'contain' => array(
2121
'Organisation' => array('id', 'name'),
22-
'Role' => array('id', 'name', 'perm_auth')
22+
'Role' => array('id', 'name', 'perm_auth', 'perm_site_admin')
2323
)
2424
);
2525

@@ -350,11 +350,16 @@ public function admin_index()
350350
),
351351
'contain' => array(
352352
'Organisation' => array('id', 'name'),
353-
'Role' => array('id', 'name', 'perm_auth')
353+
'Role' => array('id', 'name', 'perm_auth', 'perm_site_admin')
354354
)
355355
));
356356
foreach ($users as $key => $value) {
357-
unset($users['User']['password']);
357+
if (empty($this->Auth->user('Role')['perm_site_admin'])) {
358+
if ($value['Role']['perm_site_admin']) {
359+
$users[$key]['User']['authkey'] = __('Redacted');
360+
}
361+
}
362+
unset($users[$key]['User']['password']);
358363
}
359364
return $this->RestResponse->viewData($users, $this->response->type());
360365
} else {
@@ -366,7 +371,13 @@ public function admin_index()
366371
} else {
367372
$conditions['User.org_id'] = $this->Auth->user('org_id');
368373
$this->paginate['conditions']['AND'][] = $conditions;
369-
$this->set('users', $this->paginate());
374+
$users = $this->paginate();
375+
foreach ($users as $key => $value) {
376+
if ($value['Role']['perm_site_admin']) {
377+
$users[$key]['User']['authkey'] = __('Redacted');
378+
}
379+
}
380+
$this->set('users', $users);
370381
}
371382
if ($this->request->is('ajax')) {
372383
$this->autoRender = false;
@@ -462,6 +473,9 @@ public function admin_view($id = null)
462473
$user['User']['fingerprint'] = !empty($pgpDetails[4]) ? $pgpDetails[4] : 'N/A';
463474
}
464475
$user['User']['orgAdmins'] = $this->User->getOrgAdminsForOrg($user['User']['org_id'], $user['User']['id']);
476+
if (empty($this->Auth->user('Role')['perm_site_admin']) && !(empty($user['Role']['perm_site_admin']))) {
477+
$user['User']['authkey'] = __('Redacted');
478+
}
465479
$this->set('user', $user);
466480
if (!$this->_isSiteAdmin() && !($this->_isAdmin() && $this->Auth->user('org_id') == $user['User']['org_id'])) {
467481
throw new MethodNotAllowedException();
@@ -694,9 +708,10 @@ public function admin_edit($id = null)
694708
$params = array();
695709
$allowedRole = '';
696710
$userToEdit = $this->User->find('first', array(
697-
'conditions' => array('id' => $id),
711+
'conditions' => array('User.id' => $id),
698712
'recursive' => -1,
699-
'fields' => array('id', 'role_id', 'email', 'org_id'),
713+
'fields' => array('User.id', 'User.role_id', 'User.email', 'User.org_id', 'Role.perm_site_admin'),
714+
'contain' => array('Role')
700715
));
701716
if (!$this->_isSiteAdmin()) {
702717
// Org admins should be able to select the role that is already assigned to an org user when editing them.
@@ -706,8 +721,8 @@ public function admin_edit($id = null)
706721
// MISP automatically chooses the first available option for the user as the selected setting (usually user)
707722
// Org admin is downgraded to a user
708723
// Now we make an exception for the already assigned role, both in the form and the actual edit.
709-
if ($userToEdit['User']['org_id'] != $this->Auth->user('org_id')) {
710-
throw new Exception('Invalid user');
724+
if ($userToEdit['User']['org_id'] != $this->Auth->user('org_id') || !empty($userToEdit['Role']['perm_site_admin'])) {
725+
throw new NotFoundException(__('Invalid user'));
711726
}
712727
$allowedRole = $userToEdit['User']['role_id'];
713728
$params = array('conditions' => array(

Diff for: app/Model/Log.php

+27
Original file line numberDiff line numberDiff line change
@@ -295,4 +295,31 @@ public function logData($data)
295295
}
296296
return true;
297297
}
298+
299+
public function filterSiteAdminSensitiveLogs($list)
300+
{
301+
$this->User = ClassRegistry::init('User');
302+
$site_admin_roles = $this->User->Role->find('list', array(
303+
'recursive' => -1,
304+
'conditions' => array('Role.perm_site_admin' => 1),
305+
'fields' => array('Role.id', 'Role.id')
306+
));
307+
$site_admins = $this->User->find('list', array(
308+
'recursive' => -1,
309+
'conditions' => array(
310+
'User.role_id' => array_values($site_admin_roles)
311+
),
312+
'fields' => array('User.id', 'User.id')
313+
));
314+
foreach ($list as $k => $v) {
315+
if (
316+
$v['Log']['model'] === 'User' &&
317+
in_array($v['Log']['model_id'], array_values($site_admins)) &&
318+
in_array($v['Log']['action'], array('add', 'edit', 'reset_auth_key'))
319+
) {
320+
$list[$k]['Log']['change'] = __('Redacted');
321+
}
322+
}
323+
return $list;
324+
}
298325
}

0 commit comments

Comments
 (0)