CVE-2021-21327: Remotely trigerring execution of your PHP objects in GLPI

By: Vadym Soroka.

GLPI is a popular open-source ITSM and Service Center software used in many companies with mid-large IT assets inventory.

Vulnerabilities in systems like GLPI are extremely juicy for the attackers since it provides a rich source of information regarding internal IT assets. Such vulnerabilities also potentially enable lateral movement and establishing persistence in corporate networks, e.g through implanting backdoors/ransomware to the inventory of monitored hosts using GLPI FusionInventory plugin’s software deployment functionality.

Inspired by our recent external penetration test of the client’s network (SMB Software Development Company), our team decided to run some further research of the publicly available GLPI source code and has discovered a new vulnerability in this system.

Additionally, in the following posts, we are planning to share our experience regarding typical misconfigurations in GLPI systems deployed and how to prevent them.

Vulnerability summary


Product: GLPI
Vulnerable version: <=9.5.3
Tested: v9.5.3, 2021-02-14
Category: Limited PHP remote code execution
Vulnerability type: CWE-470: Use of Externally-Controlled Input to Select Classes or Code (‘Unsafe Reflection’)
CVE ID: CVE-2021-21327


Description

Any non-authenticated user can remotely instantiate an object of the class existing in the GLPI environment that can be used to carry out malicious attacks, or to start a “POP chain”.

Initial entry point

Many entry points exist in the GLPI and their plugins, where untrusted user input is passed to the getItemForItemtype function missing input and authorization checks, so just one example is shown to demonstrate the issue in the dropdownConnect.php as an entry point.

The dropdownConnect.php passes parameter  fromtype from the external POST request to the getItemForItemtype function without any authorization checks :

//--- file dropdownConnect.php:
if (!isset($_POST['fromtype']) || !($fromitem = getItemForItemtype($_POST['fromtype']))) {
exit();
}

Next, the untrusted user’s input is transmitted as an argument to the getItemForItemtype function which is responsible for object instantiation with an input class name without proper validation:

//--- file dbutils.class.php, function getItemForItemtype($itemtype)
if (class_exists($itemtype)) {
   return new $itemtype();
}
//handle namespaces
if (substr($itemtype, 0, \strlen(NS_GLPI)) === NS_GLPI) {
   $itemtype = stripslashes($itemtype);
   if (class_exists($itemtype)) {
      return new $itemtype();
   }
}

As a result of such unvalidated user input, when passing an existing class name (e.g. Glpi\Console\Application) a new object of this class is created executing its constructor e.g. magic  __construct() PHP method if declared. Subsequently, when a PHP object gets destroyed, its __destruct() method is executed.

CVE-2021-21327 exploit

Issue a request:

POST /ajax/dropdownConnect.php HTTP/1.1
Host: glpi
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Connection: close

fromtype=ClassName

where ClassName is a class name existing in a GLPI environment in the expected format to pass name validation checks, e.g. Glpi\Foo\Bar for the GLPI core classes, PluginFooBar for a GLPI Plugin.

Timeline

  • 2021.02.14: Report sent (initial severity reported as High)
  • 2021.02.16: Feedback received (triaged as Moderate)
  • 2021.02.16: Initial fix deployed
  • 2021.02.16: Review requested
  • 2021.02.16: Suggestions sent
  • 2021.02.26 CVE-2021-21327 issued
  • 2021.03.02 Fixes committed in the main branch
  • 2021.03.03 GLPI 9.5.4 is released

Security impact analysis

This vulnerability impacts the integrity and availability of the GLPI system since a malicious user can remotely call random constructors or destructors which might contain some sensitive/heavy-loading/destructive operations.

The root cause of this vulnerability is based on the usage of reflection functionality:  in many places, PHP code dynamically instantiates classes, e.g. using class name as a parameter, which can be also fed from the user input.

Proposed mitigation for this class of vulnerabilities

In the systems secured by design such behaviour should be restricted completely since a user’s (both authenticated or non-authenticated) input is not trusted. Alternatively, a strict white-list of such reflection usage should be introduced to minimize misuse potential.

By: Vadym Soroka.

More cyber security insight in our Newsletter

Categories

AppSec
Company updates
Security Research

Contact us