CVE-2016-5733 (PHP, published 2016-07-03T01:59Z)
Description: value: Multiple cross-site scripting (XSS) vulnerabilities in phpMyAdmin 4.0.x before 4.0.10.16, 4.4.x before 4.4.15.7, and 4.6.x before 4.6.3 allow remote attackers to inject arbitrary web script or HTML via vectors involving (1) a crafted table name that is mishandled during privilege checking in table_row.phtml, (2) a crafted mysqld log_bin directive that is mishandled in log_selector.phtml, (3) the Transformation implementation, (4) AJAX error handling in js/ajax.js, (5) the Designer implementation, (6) the charts implementation in js/tbl_chart.js, or (7) the zoom-search implementation in rows_zoom.phtml.
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/phpmyadmin/phpmyadmin
Files changed:
libraries/plugins/transformations/abs/DateFormatTransformationsPlugin.php
libraries/plugins/transformations/abs/DownloadTransformationsPlugin.php
libraries/plugins/transformations/abs/ImageLinkTransformationsPlugin.php
libraries/plugins/transformations/abs/InlineTransformationsPlugin.php
libraries/plugins/transformations/abs/LongToIPv4TransformationsPlugin.php
libraries/plugins/transformations/abs/PreApPendTransformationsPlugin.php
libraries/plugins/transformations/abs/SubstringTransformationsPlugin.php
libraries/plugins/transformations/abs/TextImageLinkTransformationsPlugin.php
libraries/plugins/transformations/abs/TextLinkTransformationsPlugin.php
libraries/transformations.lib.php
test/classes/plugin/transformations/TransformationPluginsTest.php
test/libraries/PMA_transformation_test.php
Commit message: Simplify and cleanup transformation plugins

Remove PMA_transformation_global_html_replace which makes the code only
more confusing.

Also add escaping to browse transformations.

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


Vulnerable code:
            $buffer = '<dfn onclick="alert(\'' . $source . '\');" title="'
                . $source . '">' . $text . '</dfn>';

        return $buffer;
            urlencode($cn),
        $transform_options = array(
            'string' => '<a class="disableAjax"'
                . ' target="_new" href="transformation_wrapper.php'
                . $options['wrapper_link'] . '" alt="[__BUFFER__]">[BLOB]</a>',
        );

        return PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );
            $transform_options = array(
                'string' => '<a href="transformation_wrapper.php'
                    . $options['wrapper_link']
                    . '" target="_blank"><img src="transformation_wrapper.php'
                    . $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
                    . (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
                    . (isset($options[1]) ? $options[1] : 100)
                    . '" alt="[__BUFFER__]" border="0" /></a>',
            );
            $transform_options = array(
                'string' => '<img src="transformation_wrapper.php'
                    . $options['wrapper_link']
                    . '" alt="[__BUFFER__]" width="320" height="240" />',
            );

        return PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );
            return $buffer;
        $newtext = htmlspecialchars($options[0]) . $buffer

        return $newtext;
        return $newtext;
/* For PMA_Transformation_globalHtmlReplace */
require_once 'libraries/transformations.lib.php';

        $transform_options = array(
            'string' => '<a href="' . (isset($options[0]) ? $options[0] : '')
                . $buffer . '" target="_blank"><img src="'
                . (isset($options[0]) ? $options[0] : '') . $buffer
                . '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
                . '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
                . $buffer . '</a>',
        );

        $buffer = PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );

        return $buffer;
/* For PMA_Transformation_globalHtmlReplace */
require_once 'libraries/transformations.lib.php';


        $transform_options = array(
            'string' => '<a href="'
                . (isset($options[0]) ? $options[0] : '') . $append_part
                . '" title="'
                . htmlspecialchars(isset($options[1]) ? $options[1] : '')
                . '" target="_new">'
                . htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
                . '</a>',
        );

        return PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );

/**
 * Replaces "[__BUFFER__]" occurrences found in $options['string'] with the text
 * in $buffer, after performing a regular expression search and replace on
 * $buffer using $options['regex'] and $options['regex_replace'].
 *
 * @param string $buffer  text that will be replaced in $options['string'],
 *                        after being formatted
 * @param array  $options the options required to format $buffer
 *     = array (
 *         'string'        => 'string', // text containing "[__BUFFER__]"
 *         'regex'         => 'mixed',  // the pattern to search for
 *         'regex_replace' => 'mixed',  // string or array of strings to replace
 *                                      // with
 *     );
 *
 * @return string containing the text with all the replacements
 */
function PMA_Transformation_globalHtmlReplace($buffer, $options = array())
{
    if (! isset($options['string'])) {
        $options['string'] = '';
    }

    if (isset($options['regex']) && isset($options['regex_replace'])) {
        $buffer = preg_replace(
            '@' . str_replace('@', '\@', $options['regex']) . '@si',
            $options['regex_replace'],
            $buffer
        );
    }

    // Replace occurrences of [__BUFFER__] with actual text
    $return = str_replace("[__BUFFER__]", $buffer, $options['string']);
    return $return;
}


                . 'newHeight=200" alt="PMA_JPEG_Inline" border="0" /></a>'
                . ' alt="PMA_IMAGE_LINK">[BLOB]</a>'
                . 'alt="PMA_PNG_Inline" border="0" /></a>'
    /**
     * Test for PMA_Transformation_globalHtmlReplace
     *
     * @return void
     */
    public function testTransformationGlobalHtmlReplace()
    {
        // Case 1
        $actual = PMA_Transformation_globalHtmlReplace('', array());
        $this->assertEquals(
            '',
            $actual
        );

        // Case 2
        $buffer = 'foobar';
        $options = array(
            'regex' => 'foo',
            'regex_replace' => 'bar',
            'string' => 'x[__BUFFER__]x'
        );
        $actual = PMA_Transformation_globalHtmlReplace($buffer, $options);
        $this->assertEquals(
            'xbarbarx',
            $actual
        );
    }


Fixed code:
require_once 'libraries/js_escape.lib.php';

            return '<dfn onclick="alert(\'' . PMA_jsFormat($source, false) . '\');" title="'
                . htmlspecialchars($source) . '">' . htmlspecialchars($text) . '</dfn>';
        } else {
            return htmlspecialchars($buffer);
            htmlspecialchars(urlencode($cn)),
        return '<a class="disableAjax" target="_new" href="transformation_wrapper.php'
            . $options['wrapper_link'] . '" alt="[' . htmlspecialchars($buffer) . ']">[BLOB]</a>';
            return '<a href="transformation_wrapper.php'
                . $options['wrapper_link']
                . '" target="_blank"><img src="transformation_wrapper.php'
                . $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
                . (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
                . (isset($options[1]) ? $options[1] : 100)
                . '" alt="[' . htmlspecialchars($buffer) . ']" border="0" /></a>';
            return '<img src="transformation_wrapper.php'
                . $options['wrapper_link']
                . '" alt="[' . htmlspecialchars($buffer) . ']" width="320" height="240" />';

            return htmlspecialchars($buffer);
        return htmlspecialchars($options[0]) . htmlspecialchars($buffer)
        return htmlspecialchars($newtext);
        return '<a href="' . htmlspecialchars(isset($options[0]) ? $options[0] : '')
            . htmlspecialchars($buffer) . '" target="_blank"><img src="'
            . htmlspecialchars(isset($options[0]) ? $options[0] : '') . htmlspecialchars($buffer)
            . '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
            . '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
            . htmlspecialchars($buffer) . '</a>';
        return '<a href="'
            . htmlspecialchars(isset($options[0]) ? $options[0] : '')
            . htmlspecialchars($append_part)
            . '" title="'
            . htmlspecialchars(isset($options[1]) ? $options[1] : '')
            . '" target="_new">'
            . htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
            . '</a>';

                . 'newHeight=200" alt="[PMA_JPEG_Inline]" border="0" /></a>'
                . ' alt="[PMA_IMAGE_LINK]">[BLOB]</a>'
                . 'alt="[PMA_PNG_Inline]" border="0" /></a>'