CVE-2020-15176 (published 2020-10-07T19:15Z)

In GLPI before version 9.5.2, when supplying a back tick in input that gets put into a SQL query,the application does not escape or sanitize allowing for SQL Injection to occur. Leveraging this vulnerability an attacker is able to exfiltrate sensitive information like passwords, reset tokens, personal details, and more. The issue is patched in version 9.5.2

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 8.6, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/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: Cédric Anne
author_date: 2020-10-06 13:51:37+02:00
msg: Merge pull request from GHSA-x93w-64x9-58qw

* Remove ability to use SQL expressions as string in criterion values

* Fix iterator syntax

Co-authored-by: Johan Cwiklinski <jcwiklinski@teclib.com>
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: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -3,7 +3,15 @@
 The present file will list all changes made to the project; according to the
 [Keep a Changelog](http://keepachangelog.com/) project.
 
-## [9.5.1] unreleased
+## [9.5.2] unreleased
+
+### API changes
+
+#### Removed
+
+- Ability to use SQL expressions as string in criterion values in SQL iterator (replaced by usage of `QueryExpression`).
+
+## [9.5.1] 2020-07-16
 
 ## [9.5.0] 2020-07-07
 

programming_language: Markdown
filename: dropdownConnectNetworkPort.php
change_type: ModificationType.MODIFY
diff: @@ -97,7 +97,7 @@ if (class_exists($_POST["itemtype"])
                'glpi_networkports_networkports' => 'networkports_id_1',
                'glpi_networkports'              => 'id', [
                   'OR'  => [
-                     'glpi_networkports_networkports.networkports_id_2' => $DB->quoteName('glpi_networkports.id')
+                     'glpi_networkports_networkports.networkports_id_2' => new QueryExpression($DB->quoteName('glpi_networkports.id'))
                   ]
                ]
             ]

programming_language: PHP
filename: crontask.class.php
change_type: ModificationType.MODIFY
diff: @@ -396,12 +396,12 @@ class CronTask extends CommonDBTM{
          // Build query for frequency and allowed hour
          $WHERE[] = ['OR' => [
             ['AND' => [
-               ['hourmin'   => ['<', $DB->quoteName('hourmax')]],
+               ['hourmin'   => ['<', new QueryExpression($DB->quoteName('hourmax'))]],
                'hourmin'   => ['<=', $hour],
                'hourmax'   => ['>', $hour]
             ]],
             ['AND' => [
-               'hourmin'   => ['>', $DB->quoteName('hourmax')],
+               'hourmin'   => ['>', new QueryExpression($DB->quoteName('hourmax'))],
                'OR'        => [
                   'hourmin'   => ['<=', $hour],
                   'hourmax'   => ['>', $hour]

programming_language: PHP
filename: dbmysql.class.php
change_type: ModificationType.MODIFY
diff: @@ -1077,7 +1077,7 @@ class DBmysql {
          $value = $value->getValue();
       } else if ($value === null || $value === 'NULL' || $value === 'null') {
          $value = 'NULL';
-      } else if (!preg_match("/^`.*?`$/", $value)) { //`field` is valid only for mysql :/
+      } else {
          //phone numbers may start with '+' and will be considered as numeric
          $value = "'$value'";
       }

programming_language: PHP
filename: dbmysqliterator.class.php
change_type: ModificationType.MODIFY
diff: @@ -589,8 +589,6 @@ class DBmysqlIterator implements Iterator, Countable {
          return $value->getQuery();
       } else if ($value instanceof \QueryExpression) {
          return $value->getValue();
-      } else if (DBmysql::isNameQuoted($value)) { //FIXME: database related
-         return $value;
       } else if ($value instanceof \QueryParam) {
          return $value->getValue();
       } else {

programming_language: PHP
filename: report.class.php
change_type: ModificationType.MODIFY
diff: @@ -393,7 +393,7 @@ class Report extends CommonGLPI{
                   'LINK'   => 'networkports_id_1',
                   'PORT_1' => 'id', [
                      'OR'     => [
-                        'LINK.networkports_id_2'   => $DB->quoteName('PORT_1.id')
+                        'LINK.networkports_id_2'   => new QueryExpression($DB->quoteName('PORT_1.id'))
                      ]
                   ]
                ]

programming_language: PHP
filename: DB.php
change_type: ModificationType.MODIFY
diff: @@ -96,7 +96,7 @@ class DB extends \GLPITestCase {
          [null, 'NULL'],
          ['null', 'NULL'],
          ['NULL', 'NULL'],
-         ['`field`', '`field`'],
+         [new \QueryExpression('`field`'), '`field`'],
          ['`field', "'`field'"]
       ];
    }

programming_language: PHP
filename: DBmysqlIterator.php
change_type: ModificationType.MODIFY
diff: @@ -562,7 +562,7 @@ class DBmysqlIterator extends DbTestCase {
       $it = $this->it->execute('foo', ['bar' => 'val']);
       $this->string($it->getSql())->isIdenticalTo("SELECT * FROM `foo` WHERE `bar` = 'val'");
 
-      $it = $this->it->execute('foo', ['bar' => '`field`']);
+      $it = $this->it->execute('foo', ['bar' => new \QueryExpression('`field`')]);
       $this->string($it->getSql())->isIdenticalTo('SELECT * FROM `foo` WHERE `bar` = `field`');
 
       $it = $this->it->execute('foo', ['bar' => '?']);

programming_language: PHP