CVE-2020-15108 (published 2020-07-17T21:15Z)

In glpi before 9.5.1, there is a SQL injection for all usages of "Clone" feature. This has been fixed in 9.5.1.

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:P/I:N/A:N)
CVSS v3 base score: 7.1, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/glpi-project/glpi
commit_details: repo_url: https://github.com/glpi-project/glpi
author: Johan Cwiklinski
author_date: 2020-07-16 08:42:46+02:00
msg: Merge pull request from GHSA-qv6w-68gq-wx2v

CVE-2020-15108

Add test to reproduce error
Add test on calendar duplication
repository: repo_url: https://github.com/glpi-project/glpi
repo_name: glpi-project/glpi
description: GLPI is a Free Asset and IT Management Software package, Data center management, ITIL Service Desk, licenses tracking and software auditing.
repo_language: PHP
owner: glpi-project
file_changes: filename: calendar.class.php
change_type: ModificationType.MODIFY
diff: @@ -201,7 +201,7 @@ class Calendar extends CommonDropdown {
     */
    function duplicate($options = []) {
 
-      $input = $this->fields;
+      $input = Toolbox::addslashes_deep($this->fields);
       unset($input['id']);
 
       if (is_array($options) && count($options)) {

programming_language: PHP
filename: commondbtm.class.php
change_type: ModificationType.MODIFY
diff: @@ -1206,7 +1206,7 @@ class CommonDBTM extends CommonGLPI {
          return false;
       }
       $new_item = new static();
-      $input = $this->fields;
+      $input = Toolbox::addslashes_deep($this->fields);
       foreach ($override_input as $key => $value) {
          $input[$key] = $value;
       }

programming_language: PHP
filename: Calendar.php
change_type: ModificationType.MODIFY
diff: @@ -254,5 +254,19 @@ class Calendar extends DbTestCase {
       $this->boolean($calendar->getFromDB($id))->isTrue();
       //should have been duplicated too.
       $this->checkXmas($calendar);
+
+      //change name, and clone again
+      $this->boolean($calendar->update(['id' => $id, 'name' => "Je s\'apelle Groot"]))->isTrue();
+
+      $calendar = new \Calendar();
+      $this->boolean($calendar->getFromDB($id))->isTrue();
+
+      $this->boolean($calendar->duplicate())->isTrue();
+      $other_id = $calendar->fields['id'];
+      $this->integer($other_id)->isGreaterThan($id);
+      $this->boolean($calendar->getFromDB($other_id))->isTrue();
+      //should have been duplicated too.
+      $this->checkXmas($calendar);
+
    }
 }

programming_language: PHP
filename: Computer.php
change_type: ModificationType.MODIFY
diff: @@ -38,6 +38,12 @@ use DbTestCase;
 
 class Computer extends DbTestCase {
 
+   protected function getUniqueString() {
+      $string = parent::getUniqueString();
+      $string .= "with a ' inside!";
+      return $string;
+   }
+
    private function getNewComputer() {
       $computer = getItemByTypeName('Computer', '_test_pc01');
       $fields   = $computer->fields;
@@ -45,7 +51,7 @@ class Computer extends DbTestCase {
       unset($fields['date_creation']);
       unset($fields['date_mod']);
       $fields['name'] = $this->getUniqueString();
-      $this->integer((int)$computer->add($fields))->isGreaterThan(0);
+      $this->integer((int)$computer->add(\Toolbox::addslashes_deep($fields)))->isGreaterThan(0);
       return $computer;
    }
 
@@ -56,7 +62,7 @@ class Computer extends DbTestCase {
       unset($pfields['date_creation']);
       unset($pfields['date_mod']);
       $pfields['name'] = $this->getUniqueString();
-      $this->integer((int)$printer->add($pfields))->isGreaterThan(0);
+      $this->integer((int)$printer->add(\Toolbox::addslashes_deep($pfields)))->isGreaterThan(0);
       return $printer;
    }
 
@@ -89,7 +95,7 @@ class Computer extends DbTestCase {
              'states_id'    => $this->getUniqueInteger(),
              'locations_id' => $this->getUniqueInteger(),
       ];
-      $this->boolean($computer->update($in))->isTrue();
+      $this->boolean($computer->update(\Toolbox::addslashes_deep($in)))->isTrue();
       $this->boolean($computer->getFromDB($computer->getID()))->isTrue();
       $this->boolean($printer->getFromDB($printer->getID()))->isTrue();
       unset($in['id']);
@@ -134,7 +140,7 @@ class Computer extends DbTestCase {
              'states_id'    => $this->getUniqueInteger(),
              'locations_id' => $this->getUniqueInteger(),
       ];
-      $this->boolean($computer->update($in2))->isTrue();
+      $this->boolean($computer->update(\Toolbox::addslashes_deep($in2)))->isTrue();
       $this->boolean($computer->getFromDB($computer->getID()))->isTrue();
       $this->boolean($printer->getFromDB($printer->getID()))->isTrue();
       unset($in2['id']);
@@ -255,7 +261,7 @@ class Computer extends DbTestCase {
              'states_id'    => $this->getUniqueInteger(),
              'locations_id' => $this->getUniqueInteger(),
       ];
-      $this->boolean($computer->update($in))->isTrue();
+      $this->boolean($computer->update(\Toolbox::addslashes_deep($in)))->isTrue();
       $this->boolean($computer->getFromDB($computer->getID()))->isTrue();
 
       $printer = new \Printer();
@@ -431,6 +437,8 @@ class Computer extends DbTestCase {
       )->isGreaterThan(0);
 
       //clone!
+      $computer = new \Computer(); //$computer->fields contents is already escaped!
+      $this->boolean($computer->getFromDB($id))->isTrue();
       $added = $computer->clone();
       $this->integer((int)$added)->isGreaterThan(0);
       $this->integer($added)->isNotEqualTo($computer->fields['id']);

programming_language: PHP