what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

phpMyAdmin 3.x Remote Code Execution

phpMyAdmin 3.x Remote Code Execution
Posted Jul 8, 2011
Authored by Mango

phpMyAdmin version 3.x suffers from multiple remote code execution vulnerabilities.

tags | exploit, remote, vulnerability, code execution
advisories | CVE-2011-2505, CVE-2011-2506, CVE-2011-2507, CVE-2011-2508
SHA-256 | 2c8f67b34ff9e950a203c8d95cb5db1edaf669e76877d659e135f52bfce8de93

phpMyAdmin 3.x Remote Code Execution

Change Mirror Download
phpMyAdmin 3.x Multiple Remote Code Executions

This post details a few interesting vulnerabilities I found while relaxing and reading the sourcecode of phpMyAdmin. My original advisory can be found here.

If you would like me to audit your PHP project, check out Xxor's PHP code auditing service.

The first vulnerability
File: libraries/auth/swekey/swekey.auth.lib.php
Lines: 266-276
Patched in: 3.3.10.2 and 3.4.3.1
Type: Variable Manipulation
Assigned CVE id: CVE-2011-2505
PMA Announcement-ID: PMASA-2011-5

266 if (strstr($_SERVER['QUERY_STRING'],'session_to_unset') != false)
267 {
268 parse_str($_SERVER['QUERY_STRING']);
269 session_write_close();
270 session_id($session_to_unset);
271 session_start();
272 $_SESSION = array();
273 session_write_close();
274 session_destroy();
275 exit;
276 }

Notice the call to parse_str on line 268 that passes the query string as it's first argument. It's missing a second argument. This means that what ever parameters and values are present in the query string will be used as variables in the current namespace. But since the code path that executes the call to parse_str inevitably leads to a call to exit there ain't much to exploit. However the session variables persists between requests. Thus giving us full control of the $_SESSION array.

From here on there are numerous XSS and SQL injection vulnerabilities open for attack. But we'll focus on three far more serious vulnerabilities.


The second vulnerability
Patched in: 3.3.10.2 and 3.4.3.1
Type: Remote Static Code Injection
Assigned CVE id: CVE-2011-2506
PMA Announcement-ID: PMASA-2011-6

File: setup/lib/ConfigGenerator.class.php
Lines: 16-78
16 /**
17 * Creates config file
18 *
19 * @return string
20 */
21 public static function getConfigFile()
22 {
23 $cf = ConfigFile::getInstance();
24
25 $crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";
26 $c = $cf->getConfig();
27
28 // header
29 $ret = '<!--?php' . $crlf
30 . '/*' . $crlf
31 . ' * Generated configuration file' . $crlf
32 . ' * Generated by: phpMyAdmin '
33 . $GLOBALS['PMA_Config']--->get('PMA_VERSION')
34 . ' setup script' . $crlf
35 . ' * Date: ' . date(DATE_RFC1123) . $crlf
36 . ' */' . $crlf . $crlf;
37
38 // servers
39 if ($cf->getServerCount() > 0) {
40 $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf . $crlf;
41 foreach ($c['Servers'] as $id => $server) {
42 $ret .= '/* Server: ' . strtr($cf->getServerName($id), '*/', '-') . " [$id] */" . $crlf
43 . '$i++;' . $crlf;
44 foreach ($server as $k => $v) {
45 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
46 $ret .= "\$cfg['Servers'][\$i]['$k'] = "
47 . (is_array($v) && self::_isZeroBasedArray($v)
48 ? self::_exportZeroBasedArray($v, $crlf)
49 : var_export($v, true))
50 . ';' . $crlf;
51 }
52 $ret .= $crlf;
53 }
54 $ret .= '/* End of servers configuration */' . $crlf . $crlf;
55 }
56 unset($c['Servers']);
57
58 // other settings
59 $persistKeys = $cf->getPersistKeysMap();
60
61 foreach ($c as $k => $v) {
62 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
63 $ret .= self::_getVarExport($k, $v, $crlf);
64 if (isset($persistKeys[$k])) {
65 unset($persistKeys[$k]);
66 }
67 }
68 // keep 1d array keys which are present in $persist_keys (config.values.php)
69 foreach (array_keys($persistKeys) as $k) {
70 if (strpos($k, '/') === false) {
71 $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
72 $ret .= self::_getVarExport($k, $cf->getDefault($k), $crlf);
73 }
74 }
75 $ret .= '?>';
76
77 return $ret;
78 }

On line 42 in this file a comment is created to show some additional information in a config file. We can see that the output of the call to $cf->getServerName($id) is sanitized to prevent user input from closing the comment. However $id, the key of the $c['Servers'] array, is not. So if we could rename a key in this array we could close the comment and inject arbitrary PHP code.
On line 26 the $c array is created from a call to $cf->getConfig().

File: libraries/config/ConfigFile.class.php
Lines: 469-482
469 /**
470 * Returns configuration array (full, multidimensional format)
471 *
472 * @return array
473 */
474 public function getConfig()
475 {
476 $c = $_SESSION[$this->id];
477 foreach ($this->cfgUpdateReadMapping as $map_to => $map_from) {
478 PMA_array_write($map_to, $c, PMA_array_read($map_from, $c));
479 PMA_array_remove($map_from, $c);
480 }
481 return $c;
482 }

Bingo! The $c array is derived from the $_SESSION array hence we could have full control of its contents by utilizing the first vulnerability. Now we can inject arbitrary PHP code that will be saved into the file config/config.inc.php. Then we would just browse to this file and the webserver would executed it.

This vulnerability requires one specific condition. The config directory must have been left in place after the initial configuration. This is something advised against and hence a majority of servers wont be susceptible to this attack. Therefor we'll check out a third and a fourth vulnerability.


The third vulnerability
Patched in: 3.3.10.2 and 3.4.3.1
Type: Authenticated Remote Code Execution
Assigned CVE id: CVE-2011-2507
PMA Announcement-ID: PMASA-2011-7

File: server_synchronize.php
Line: 466
466 $trg_db = $_SESSION['trg_db'];
Line: 477
477 $uncommon_tables = $_SESSION['uncommon_tables'];
Line: 674
674 PMA_createTargetTables($src_db, $trg_db, $src_link, $trg_link, $uncommon_tables, $uncommon_table_structure_diff[$s], $uncommon_tables_fields, false);
File: libraries/server_synchronize.lib.php
Lines: 613-631
613 function PMA_createTargetTables($src_db, $trg_db, $src_link, $trg_link, &$uncommon_tables, $table_index, &$uncommon_tables_fields, $display)
614 {
615 if (isset($uncommon_tables[$table_index])) {
616 $fields_result = PMA_DBI_get_fields($src_db, $uncommon_tables[$table_index], $src_link);
617 $fields = array();
618 foreach ($fields_result as $each_field) {
619 $field_name = $each_field['Field'];
620 $fields[] = $field_name;
621 }
622 $uncommon_tables_fields[$table_index] = $fields;
623
624 $Create_Query = PMA_DBI_fetch_value("SHOW CREATE TABLE " . PMA_backquote($src_db) . '.' . PMA_backquote($uncommon_tables[$table_index]), 0, 1, $src_link);
625
626 // Replace the src table name with a `dbname`.`tablename`
627 $Create_Table_Query = preg_replace('/' . PMA_backquote($uncommon_tables[$table_index]) . '/',
628 PMA_backquote($trg_db) . '.' .PMA_backquote($uncommon_tables[$table_index]),
629 $Create_Query,
630 $limit = 1
631 );

The variables $uncommon_tables[$table_index] and $trg_db are derived from the $_SESSION array. By utilizing the first vulnerability we can inject what ever we want into both the first and the second argument of the function preg_replace on lines 627-631. In a previous post to this blog I've detailed how this condition can be turned into a remote code execution. Basicly we can inject the "e" modifier into the regexp pattern which causes the second argument to be executed as PHP code.

This vulnerability have two major restrictions from an attackers perspective. First the Suhosin patch that completly defends against this type of attack. Second, this piece of code can only be reached if we're authenticated. So to exploit it we would need to have previous knowledge of credentials to an account of the database that phpMyAdmin is set up to manage. Except for some obscure configurations that allows us to bypass this restriction.

Since the Suhosin patch is pretty popular, and for example compiled by default in OpenBSD's PHP packages, it's worth exploring a fourth vulnerability.


The fourth vulnerability
Patched in: 3.3.10.2 and 3.4.3.1
Type: Path Traversal
Assigned CVE id: CVE-2011-2508
PMA Announcement-ID: PMASA-2011-8

File: libraries/display_tbl.lib.php
Lines: 1291-1299
1291 if ($GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME']) {
1292
1293 if (isset($GLOBALS['mime_map'][$meta->name]['mimetype']) && isset($GLOBALS['mime_map'][$meta->name]['transformation']) && !empty($GLOBALS['mime_map'][$meta->name]['transformation'])) {
1294 $include_file = $GLOBALS['mime_map'][$meta->name]['transformation'];
1295
1296 if (file_exists('./libraries/transformations/' . $include_file)) {
1297 $transformfunction_name = str_replace('.inc.php', '', $GLOBALS['mime_map'][$meta->name]['transformation']);
1298
1299 require_once './libraries/transformations/' . $include_file;


This fourth vulnerability is a directory traversal in a call to require_once which can be exploited as a local file inclusion. The variable $GLOBALS['mime_map'][$meta->name]['transformation'] is derived from user input. For example, by setting $GLOBALS['mime_map'][$meta->name]['transformation'] to "../../../../../../etc/passwd" the local passwd-file could show up.

This vulnerability can only be reached if we're authenticated and requires that the transformation feature is setup correctly in phpMyAdmin's configuration storage. However, the $GLOBALS['cfgRelation'] array is derived from the $_SESSION array. Hence the variable $GLOBALS['cfgRelation']['mimework'] used to check this can be modified using the first vulnerability.

File: libraries/display_tbl.lib.php
Lines: 707-710
707 if ($GLOBALS['cfgRelation']['commwork'] && $GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME'] && ! $_SESSION['tmp_user_values']['hide_transformation']) {
708 require_once './libraries/transformations.lib.php';
709 $GLOBALS['mime_map'] = PMA_getMIME($db, $table);
710 }
And the fact that $GLOBALS['mime_map'] is conditionally initialized together with the fact that phpMyAdmin registers all request variables in the global namespace (blacklists some, but not mime_map) allows us to set $GLOBALS['mime_map'][$meta->name]['transformation'] to whatever we want, even when the transformation feature is not setup correctly.


Summary

If the config folder is left in place, phpMyAdmin is vulnerable.

If an attacker has access to database credentials and the Suhosin patch is not installed, phpMyAdmin is vulnerable.

If an attacker has access to database credentials and knows how to exploit a local file inclution, phpMyAdmin is vulnerable.


Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    63 Files
  • 14
    Nov 14th
    18 Files
  • 15
    Nov 15th
    0 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close