CVE-2021-21324 (PHP, published 2021-03-08T17:15Z)
Description: value: GLPI is an open-source asset and IT management software package that provides ITIL Service Desk features, licenses tracking and software auditing. In GLPI before version 9.5.4 there is an Insecure Direct Object Reference (IDOR) on "Solutions". This vulnerability gives an unauthorized user the ability to enumerate GLPI items names (including users logins) using the knowbase search form (requires authentication). To Reproduce: Perform a valid authentication at your GLPI instance, Browse the ticket list and select any open ticket, click on Solution form, then Search a solution form that will redirect you to the endpoint /"glpi/front/knowbaseitem.php?item_itemtype=Ticket&item_items_id=18&forcetab=Knowbase$1", and the item_itemtype=Ticket parameter present in the previous URL will point to the PHP alias of glpi_tickets table, so just replace it with "Users" to point to glpi_users table instead; in the same way, item_items_id=18 will point to the related column id, so changing it too you should be able to enumerate all the content which has an alias. Since such id(s) are obviously incremental, a malicious party could exploit the vulnerability simply by guessing-based attempts.
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-639 \u2014 Authorization Bypass Through User-Controlled Key
The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.
Repository: https://github.com/glpi-project/glpi
Files changed:
ajax/dropdownTrackingDeviceType.php
inc/computer_item.class.php
inc/dropdown.class.php
inc/user.class.php
tests/functionnal/Dropdown.php
tests/functionnal/Session.php
Commit message: validate entity_restrict when available with idor tokens


Vulnerable code:
      '_idor_token'         => Session::getNewIDORToken($itemtype),
         '_idor_token'     => Session::getNewIDORToken($itemtype),
            'entity_restrict'      => (is_array($params['entity']) ? json_encode(array_values($params['entity'])) : $params['entity']),
            '_idor_token'          => Session::getNewIDORToken($itemtype),
      // check if asked itemtype is the one originaly requested by the form
      if (!Session::validateIDOR($post)) {
         return;
      }

         'entity_restrict'     => (is_array($p['entity']) ? json_encode(array_values($p['entity'])) : $p['entity']),
         '_idor_token'         => Session::getNewIDORToken(__CLASS__, ['right' => $p['right']]),
      $params['_idor_token'] = \Session::getNewIDORToken($params['itemtype'] ?? '');
      $params['_idor_token'] = \Session::getNewIDORToken($params['itemtype'] ?? '');

Fixed code:
      '_idor_token'         => Session::getNewIDORToken($itemtype, [
         'entity_restrict' => $_POST['entity_restrict'],
      ]),
         '_idor_token'     => Session::getNewIDORToken($itemtype, [
            'entity_restrict' => $entity_restrict,
         ]),
            'entity_restrict'      => ($entity_restrict = (is_array($params['entity']) ? json_encode(array_values($params['entity'])) : $params['entity'])),
            '_idor_token'          => Session::getNewIDORToken($itemtype, [
               'entity_restrict' => $entity_restrict,
            ]),
      // check if asked itemtype is the one originaly requested by the form
      if (!Session::validateIDOR($post)) {
         return;
      }

         'entity_restrict'     => ($entity_restrict = (is_array($p['entity']) ? json_encode(array_values($p['entity'])) : $p['entity'])),
         '_idor_token'         => Session::getNewIDORToken(__CLASS__, [
            'right'           => $p['right'],
            'entity_restrict' => $entity_restrict,
         ]),
      $params['_idor_token'] = $this->generateIdor($params);
      $params['_idor_token'] = $this->generateIdor($params);

   private function generateIdor(array $params = []) {
      $idor_add_params = [];
      if (isset($params['entity_restrict'])) {
         $idor_add_params['entity_restrict'] = $params['entity_restrict'];
      }
      return \Session::getNewIDORToken(($params['itemtype'] ?? ''), $idor_add_params);
   }
         ['itemtype' => 'User', 'add_params' => ['entity_restrict' => 0]],