CVE-2020-15226: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: In GLPI before version 9.5.2, there is a SQL Injection in the API's search function. Not only is it possible to break the SQL syntax, but it is also possible to utilise a UNION SELECT query to reflect sensitive information such as the current database version, or database user. The most likely scenario for this vulnerability is with someone who has an API account to the system. The issue is patched in version 9.5.2. A proof-of-concept with technical details is available in the linked advisory.
CWE 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.
CVSS v3 base score: 4.3
Published: 2020-10-07T20:15Z
Repository: https://github.com/glpi-project/glpi
Language: PHP
Files changed: inc/api/api.class.php
Commit date: 2020-10-06 13:37:23 +0200
Commit message: Merge pull request from GHSA-jwpv-7m4h-5gvc

* Prevent SQL injection through search API

* better solution
Diff: diff --git a/inc/api/api.class.php b/inc/api/api.class.php
index 134582c72d3..26baa5100f2 100644
--- a/inc/api/api.class.php
+++ b/inc/api/api.class.php
@@ -1629,12 +1629,12 @@ abstract class API extends CommonGLPI {
 
       // Check the criterias are valid
       if (isset($params['criteria']) && is_array($params['criteria'])) {
 
          // use a recursive closure to check each nested criteria
-         $check_criteria = function($criteria) use (&$check_criteria, $soptions) {
-            foreach ($criteria as $criterion) {
+         $check_criteria = function(&$criteria) use (&$check_criteria, $soptions) {
+            foreach ($criteria as &$criterion) {
                // recursive call
                if (isset($criterion['criteria'])) {
                   return $check_criteria($criterion['criteria']);
                }
 
@@ -1651,10 +1651,13 @@ abstract class API extends CommonGLPI {
                if (isset($soptions[$criterion['field']])
                    && isset($soptions[$criterion['field']]['nosearch'])
                    && $soptions[$criterion['field']]['nosearch']) {
                   return __("Forbidden field ID in search criteria");
                }
+
+               // Escape value to prevent SQL injection
+               $criterion['value'] = Toolbox::addslashes_deep($criterion['value']);
             }
 
             return true;
          };
 

Vulnerable code:          $check_criteria = function($criteria) use (&$check_criteria, $soptions) {
            foreach ($criteria as $criterion) {
Fixed code:          $check_criteria = function(&$criteria) use (&$check_criteria, $soptions) {
            foreach ($criteria as &$criterion) {

               // Escape value to prevent SQL injection
               $criterion['value'] = Toolbox::addslashes_deep($criterion['value']);