CVE-2019-12794 (PHP, published 2019-06-11T17:29Z)
Description: value: An issue was discovered in MISP 2.4.108. Organization admins could reset credentials for site admins (organization admins have the inherent ability to reset passwords for all of their organization's users). This, however, could be abused in a situation where the host organization of an instance creates organization admins. An organization 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 only occurs when the host organization creates lower-privilege organization admins instead of the usual site admins. Also, only organization admins of the same organization as the site admin could abuse this.
Severity: MEDIUM (CVSS v3 base score: 6.6)
Weakness: CWE-269 \u2014 Improper Privilege Management
The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
Repository: https://github.com/MISP/MISP
Files changed:
app/Controller/LogsController.php
app/Controller/UsersController.php
app/Model/Log.php
Commit message: 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


Vulnerable code:
                $this->set('list', $this->paginate());
                $this->set('list', $this->paginate());
                'Role' => array('id', 'name', 'perm_auth')
                            'Role' => array('id', 'name', 'perm_auth')
                unset($users['User']['password']);
                $this->set('users', $this->paginate());
                'conditions' => array('id' => $id),
                'fields' => array('id', 'role_id', 'email', 'org_id'),
            if ($userToEdit['User']['org_id'] != $this->Auth->user('org_id')) {
                throw new Exception('Invalid user');

Fixed code:
                $list = $this->paginate();
                if (empty($this->Auth->user('Role')['perm_site_admin'])) {
                    $list = $this->Log->filterSiteAdminSensitiveLogs($list);
                }
                $this->set('list', $list);
                $list = $this->paginate();
                if (empty($this->Auth->user('Role')['perm_site_admin'])) {
                    $list = $this->Log->filterSiteAdminSensitiveLogs($list);
                }
                $this->set('list', $list);
                'Role' => array('id', 'name', 'perm_auth', 'perm_site_admin')
                            'Role' => array('id', 'name', 'perm_auth', 'perm_site_admin')
                if (empty($this->Auth->user('Role')['perm_site_admin'])) {
                    if ($value['Role']['perm_site_admin']) {
                        $users[$key]['User']['authkey'] = __('Redacted');
                    }
                }
                unset($users[$key]['User']['password']);
                $users = $this->paginate();
                foreach ($users as $key => $value) {
                    if ($value['Role']['perm_site_admin']) {
                        $users[$key]['User']['authkey'] = __('Redacted');
                    }
                }
                $this->set('users', $users);
        if (empty($this->Auth->user('Role')['perm_site_admin']) && !(empty($user['Role']['perm_site_admin']))) {
            $user['User']['authkey'] = __('Redacted');
        }
                'conditions' => array('User.id' => $id),
                'fields' => array('User.id', 'User.role_id', 'User.email', 'User.org_id', 'Role.perm_site_admin'),
                'contain' => array('Role')
            if ($userToEdit['User']['org_id'] != $this->Auth->user('org_id') || !empty($userToEdit['Role']['perm_site_admin'])) {
                throw new NotFoundException(__('Invalid user'));

    public function filterSiteAdminSensitiveLogs($list)
    {
        $this->User = ClassRegistry::init('User');
        $site_admin_roles = $this->User->Role->find('list', array(
            'recursive' => -1,
            'conditions' => array('Role.perm_site_admin' => 1),
            'fields' => array('Role.id', 'Role.id')
        ));
        $site_admins = $this->User->find('list', array(
            'recursive' => -1,
            'conditions' => array(
                'User.role_id' => array_values($site_admin_roles)
            ),
            'fields' => array('User.id', 'User.id')
        ));
        foreach ($list as $k => $v) {
            if (
                $v['Log']['model'] === 'User' &&
                in_array($v['Log']['model_id'], array_values($site_admins)) &&
                in_array($v['Log']['action'], array('add', 'edit', 'reset_auth_key'))
            ) {
                $list[$k]['Log']['change'] = __('Redacted');
            }
        }
        return $list;
    }