Vulnerability: SQL injection vulnerability in libraries/central_columns.lib.php in phpMyAdmin 4.4.x before 4.4.15.7 and 4.6.x before 4.6.3 allows remote attackers to execute arbitrary SQL commands via a crafted database name that is mishandled in a central column query.
Vulnerability ID: CVE-2016-5703
CWE: CWE-89
Severity score: 6.4
Project: https://github.com/phpmyadmin/phpmyadmin
Published: 2016-07-03
File: libraries/central_columns.lib.php
Commit message: Properly escape database name in central column queries

Signed-off-by: Michal Čihař <michal@cihar.com>
Commit author: Michal Čihař

Vulnerable version (before fix):
 function PMA_getColumnsList($db, $from=0, $num=25)     //get current values of $db from central column list     if ($num == 0) {         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . $db . '\';';     } else {         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . $db . '\' '             . 'LIMIT ' . $from . ', ' . $num . ';';     }     $has_list = (array) $GLOBALS['dbi']->fetchResult( function PMA_getCentralColumnsCount($db)     $central_list_table = $cfgCentralColumns['table'];     $query = 'SELECT count(db_name) FROM ' .         Util::backquote($central_list_table) . ' '         . 'WHERE db_name = \'' . $db . '\';';     $res = $GLOBALS['dbi']->fetchResult(         $query, null, null, $GLOBALS['controllink']     ); function PMA_findExistingColNames($db, $cols, $allFields=false)     $central_list_table = $cfgCentralColumns['table'];     if ($allFields) {         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';         $has_list = (array) $GLOBALS['dbi']->fetchResult(             $query, null, null, $GLOBALS['controllink']         );         PMA_handleColumnExtra($has_list);     } else {         $query = 'SELECT col_name FROM '             . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';         $has_list = (array) $GLOBALS['dbi']->fetchResult(             $query, null, null, $GLOBALS['controllink']         ); function PMA_deleteColumnsFromList($field_select, $isTable=true)     $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);      $query = 'DELETE FROM ' . Util::backquote($central_list_table) . ' '         . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';      if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {         $message = Message::error(__('Could not remove columns!')); function PMA_getCentralColumnsListRaw($db, $table)     $centralTable = $cfgCentralColumns['table'];     if (empty($table) || $table == '') {         $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '             . 'WHERE db_name = \'' . $db . '\';';     } else {         $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);         $columns = (array) $GLOBALS['dbi']->getColumnNames( function PMA_getCentralColumnsListRaw($db, $table)         }         $cols = trim($cols, ',');         $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '             . 'WHERE db_name = \'' . $db . '\'';         if ($cols) {             $query .= ' AND col_name NOT IN (' . $cols . ')';         }

Fixed version (after fix):
 function PMA_getColumnsList($db, $from=0, $num=25)     //get current values of $db from central column list     if ($num == 0) {         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\';';     } else {         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' '             . 'LIMIT ' . $from . ', ' . $num . ';';     }     $has_list = (array) $GLOBALS['dbi']->fetchResult( function PMA_getCentralColumnsCount($db)     $central_list_table = $cfgCentralColumns['table'];     $query = 'SELECT count(db_name) FROM ' .         Util::backquote($central_list_table) . ' '         . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\';';     $res = $GLOBALS['dbi']->fetchResult(         $query, null, null, $GLOBALS['controllink']     ); function PMA_findExistingColNames($db, $cols, $allFields=false)     $central_list_table = $cfgCentralColumns['table'];     if ($allFields) {         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' AND col_name IN (' . $cols . ');';         $has_list = (array) $GLOBALS['dbi']->fetchResult(             $query, null, null, $GLOBALS['controllink']         );         PMA_handleColumnExtra($has_list);     } else {         $query = 'SELECT col_name FROM '             . Util::backquote($central_list_table) . ' '             . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' AND col_name IN (' . $cols . ');';         $has_list = (array) $GLOBALS['dbi']->fetchResult(             $query, null, null, $GLOBALS['controllink']         ); function PMA_deleteColumnsFromList($field_select, $isTable=true)     $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);      $query = 'DELETE FROM ' . Util::backquote($central_list_table) . ' '         . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' AND col_name IN (' . $cols . ');';      if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {         $message = Message::error(__('Could not remove columns!')); function PMA_getCentralColumnsListRaw($db, $table)     $centralTable = $cfgCentralColumns['table'];     if (empty($table) || $table == '') {         $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '             . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\';';     } else {         $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);         $columns = (array) $GLOBALS['dbi']->getColumnNames( function PMA_getCentralColumnsListRaw($db, $table)         }         $cols = trim($cols, ',');         $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '             . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\'';         if ($cols) {             $query .= ' AND col_name NOT IN (' . $cols . ')';         }

Patch:
patch: @@ -60,10 +60,10 @@ function PMA_getColumnsList($db, $from=0, $num=25)
     //get current values of $db from central column list
     if ($num == 0) {
         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '
-            . 'WHERE db_name = \'' . $db . '\';';
+            . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\';';
     } else {
         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '
-            . 'WHERE db_name = \'' . $db . '\' '
+            . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' '
             . 'LIMIT ' . $from . ', ' . $num . ';';
     }
     $has_list = (array) $GLOBALS['dbi']->fetchResult(
@@ -91,7 +91,7 @@ function PMA_getCentralColumnsCount($db)
     $central_list_table = $cfgCentralColumns['table'];
     $query = 'SELECT count(db_name) FROM ' .
         Util::backquote($central_list_table) . ' '
-        . 'WHERE db_name = \'' . $db . '\';';
+        . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\';';
     $res = $GLOBALS['dbi']->fetchResult(
         $query, null, null, $GLOBALS['controllink']
     );
@@ -122,15 +122,15 @@ function PMA_findExistingColNames($db, $cols, $allFields=false)
     $central_list_table = $cfgCentralColumns['table'];
     if ($allFields) {
         $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '
-            . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
+            . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' AND col_name IN (' . $cols . ');';
         $has_list = (array) $GLOBALS['dbi']->fetchResult(
             $query, null, null, $GLOBALS['controllink']
         );
         PMA_handleColumnExtra($has_list);
     } else {
         $query = 'SELECT col_name FROM '
             . Util::backquote($central_list_table) . ' '
-            . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
+            . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' AND col_name IN (' . $cols . ');';
         $has_list = (array) $GLOBALS['dbi']->fetchResult(
             $query, null, null, $GLOBALS['controllink']
         );
@@ -376,7 +376,7 @@ function PMA_deleteColumnsFromList($field_select, $isTable=true)
     $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
 
     $query = 'DELETE FROM ' . Util::backquote($central_list_table) . ' '
-        . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
+        . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' AND col_name IN (' . $cols . ');';
 
     if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
         $message = Message::error(__('Could not remove columns!'));
@@ -1147,7 +1147,7 @@ function PMA_getCentralColumnsListRaw($db, $table)
     $centralTable = $cfgCentralColumns['table'];
     if (empty($table) || $table == '') {
         $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '
-            . 'WHERE db_name = \'' . $db . '\';';
+            . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\';';
     } else {
         $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
         $columns = (array) $GLOBALS['dbi']->getColumnNames(
@@ -1159,7 +1159,7 @@ function PMA_getCentralColumnsListRaw($db, $table)
         }
         $cols = trim($cols, ',');
         $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '
-            . 'WHERE db_name = \'' . $db . '\'';
+            . 'WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\'';
         if ($cols) {
             $query .= ' AND col_name NOT IN (' . $cols . ')';
         }
path: libraries/central_columns.lib.php