phpMyAdmin Tracking XSS-Vulnerability

Type: persistent XSSNorman Hippert — Company: sudos.ec — (wildcat at the-wildcat dot de)

  • Reported: 26.07.2011
  • Published: 25.08.2011
  • Updated: 25.08.2011
  • Affected versions: 3.3.0 - 3.4.3.1
  • Risk: moderate to high
  • Solution: Upgrade to 3.4.4 or 3.3.10.4 or newer
  • CVE-ID: CVE-2011-3181

Description

The phpMyAdmin structure snapshot functionality is susceptible to XSS.
The column and index name isn't properly sanitized, which allows an attacker to execute javascript within site context.

Using Internet Explorer <= 8.x it's possible to execute javascript via the tracking export feature. This is possible, because Internet Explorer stops to interpret filename's in the attachment header at the first semicolon. A specially crafted tablename like test.html; causes XSS.
Because content-type determination in IE is somewhat complicated, have a look at the following graphic.

Internet Explorer Content-Type determination
Taken from "Make a contract with IE and become a XSS girl!"

In addition, the tracking report functionality also suffers from XSS vulnerabilities. We consider this to be not exploitable, because the attacker needs a valid token to manipulate the URL parameters.

The attacker needs access to the victims database (shared hosting setups for example) and the CREATE or ALTER TABLE right.
The tracking feature has to be enabled and the victim has to use the tracking feature.

Some shameless self promotion: Need help securing your (web) applications? Write an e-mail to wildcat at the-wildcat dot de or contact me on XING :mrgreen:

GET /phpMyAdmin/tbl_tracking.php?db=test&table=XSS+-+phpMyAdmin+-+3.4.3.2&token=0920d634a3939ee0e60be7f408b1c7ba&goto=tbl_tracking.php&back=tbl_tracking.php&snapshot=true&version=1 HTTP/1.1
Host: fd.sudos.ec
  • File: phpMyAdmin/tbl_tracking.php
  • Line: 279-295
foreach($columns as $field_index => $field) {
?>
        <tr class="noclick <?php echo $style; ?>">
            <?php
            if ($field['Key'] == 'PRI') {
                echo '<td><b><u>' . $field['Field'] . '</u></b></td>' . "\n";
            } else {
                echo '<td><b>' . $field['Field'] . '</b></td>' . "\n";
            }
            ?>
            <td><?php echo $field['Type'];?></td>
            <td><?php echo $field['Collation'];?></td>
            <td><?php echo $field['Null'];?></td>
            <td><?php echo $field['Default'];?></td>
            <td><?php echo $field['Extra'];?></td>
            <td><?php echo $field['Comment'];?></td>
        </tr>
phpMyAdmin-3.3-3.4 XSS Tracking Report

  • File: phpMyAdmin/tbl_tracking.php
  • Line: 114-124
  • Replace all semicolons within filename, with, for example, _
    $filename = 'log_' . htmlspecialchars($_REQUEST['table']) . '.sql';
    header('Content-Type: text/x-sql');
    header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    if (PMA_USR_BROWSER_AGENT == 'IE') {
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
    } else {
        header('Pragma: no-cache');
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    }
phpMyAdmin-3.3-3.4 XSS Tracking Export

  • File: phpMyAdmin/tbl_tracking.php
  • Line: 378-388
    <form method="post" action="tbl_tracking.php?<?php echo $url_query; ?>&amp;report=true&amp;version=<?php echo $_REQUEST['version'];?>">
    <?php

    $str1 = '<select name="logtype">' .
            '<option value="schema"' . ($selection_schema ? ' selected="selected"' : '') . '>' . __('Structure only') . '</option>' .
            '<option value="data"' . ($selection_data ? ' selected="selected"' : ''). '>' . __('Data only') . '</option>' .
            '<option value="schema_and_data"' . ($selection_both ? ' selected="selected"' : '') . '>' . __('Structure and data') . '</option>' .
            '</select>';
    $str2 = '<input type="text" name="date_from" value="' . $_REQUEST['date_from'] . '" size="19" />';
    $str3 = '<input type="text" name="date_to" value="' . $_REQUEST['date_to'] . '" size="19" />';
    $str4 = '<input type="text" name="users" value="' . $_REQUEST['users'] . '" />';
    $str5 = '<input type="submit" name="list_report" value="' . __('Go') . '" />';
  • File: phpMyAdmin/tbl_tracking.php
  • Line: 496-515
    <form method="post" action="tbl_tracking.php?<?php echo $url_query; ?>&amp;report=true&amp;version=<?php echo $_REQUEST['version'];?>">
    <?php
    printf(__('Show %s with dates from %s to %s by user %s %s'), $str1, $str2, $str3, $str4, $str5);

    $str_export1 =  '<select name="export_type">' .
                    '<option value="sqldumpfile">' . __('SQL dump (file download)') . '</option>' .
                    '<option value="sqldump">' . __('SQL dump') . '</option>' .
                    '<option value="execution" onclick="alert(\'' . PMA_escapeJsString(__('This option will replace your table and contained data.')) .'\')">' . __('SQL execution') . '</option>' .
                    '</select>';

    $str_export2 = '<input type="submit" name="report_export" value="' . __('Go') .'" />';
    ?>
    </form>
    <form method="post" action="tbl_tracking.php?<?php echo $url_query; ?>&amp;report=true&amp;version=<?php echo $_REQUEST['version'];?>">
    <input type="hidden" name="logtype" value="<?php echo $_REQUEST['logtype'];?>" />
    <input type="hidden" name="date_from" value="<?php echo $_REQUEST['date_from'];?>" />
    <input type="hidden" name="date_to" value="<?php echo $_REQUEST['date_to'];?>" />
    <input type="hidden" name="users" value="<?php echo $_REQUEST['users'];?>" />
    <?php
    echo "<br/>" . sprintf(__('Export as %s'), $str_export1) . $str_export2 . "<br/>";
phpMyAdmin-3.4.3.1 Remote Code Execution

There possibly are more vulnerable code parts in this file. Please take a closer look, during fixing. Thanks :)