diff --git a/ChangeLog b/ChangeLog index 6d21bae074..eedec420c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,12 @@ phpMyAdmin - ChangeLog 3.5.9.0 (not yet released) +3.5.8.1 (2013-04-24) +- [security] Remote code execution (preg_replace), reported by Janek Vind + (see PMASA-2013-2) +- [security] Locally Saved SQL Dump File Multiple File Extension Remote Code + Execution, reported by Janek Vind (see PMASA-2013-3) + 3.5.8.0 (2013-04-08) - bug #3828 MariaDB reported as MySQL - bug #3854 Incorrect header for Safari 6.0 diff --git a/export.php b/export.php index 7036af9277..6084cafc5f 100644 --- a/export.php +++ b/export.php @@ -273,7 +273,9 @@ if ($asfile) { } } $filename = PMA_expandUserString($filename_template); - $filename = PMA_sanitize_filename($filename); + // remove dots in filename (coming from either the template or already + // part of the filename) to avoid a remote code execution vulnerability + $filename = PMA_sanitize_filename($filename, $replaceDots = true); // Grab basic dump extension and mime type // Check if the user already added extension; get the substring where the extension would be if it was included diff --git a/libraries/Tracker.class.php b/libraries/Tracker.class.php index 2f50623832..3d27f896a8 100644 --- a/libraries/Tracker.class.php +++ b/libraries/Tracker.class.php @@ -877,6 +877,9 @@ class PMA_Tracker if (empty($dbname)) { return; } + // Remove null bytes (preg_replace() is vulnerable in some + // PHP versions) + $dbname = str_replace("\0", "", $dbname); // If we found a valid statement if (isset($result['identifier'])) { diff --git a/libraries/mult_submits.inc.php b/libraries/mult_submits.inc.php index 30654922eb..1eafb96c3d 100644 --- a/libraries/mult_submits.inc.php +++ b/libraries/mult_submits.inc.php @@ -425,14 +425,23 @@ if (!empty($submit_mult) && !empty($what)) { case 'replace_prefix_tbl': $current = $selected[$i]; - $newtablename = preg_replace("/^" . $from_prefix . "/", $to_prefix, $current); + if (substr($current, 0, strlen($from_prefix)) == $from_prefix) { + $newtablename = $to_prefix . substr($current, strlen($from_prefix)); + } else { + $newtablename = $current; + } $a_query = 'ALTER TABLE ' . PMA_backquote($selected[$i]) . ' RENAME ' . PMA_backquote($newtablename) ; // CHANGE PREFIX PATTERN $run_parts = true; break; case 'copy_tbl_change_prefix': $current = $selected[$i]; - $newtablename = preg_replace("/^" . $from_prefix . "/", $to_prefix, $current); + if (substr($current, 0, strlen($from_prefix)) == $from_prefix) { + $newtablename = $to_prefix . substr($current, strlen($from_prefix)); + } else { + $newtablename = $current; + } + $newtablename = $to_prefix . substr($current, strlen($from_prefix)); $a_query = 'CREATE TABLE ' . PMA_backquote($newtablename) . ' SELECT * FROM ' . PMA_backquote($selected[$i]) ; // COPY TABLE AND CHANGE PREFIX PATTERN $run_parts = true; break; diff --git a/libraries/sanitizing.lib.php b/libraries/sanitizing.lib.php index 1f3110f305..111fdf3859 100644 --- a/libraries/sanitizing.lib.php +++ b/libraries/sanitizing.lib.php @@ -134,18 +134,29 @@ function PMA_sanitize($message, $escape = false, $safe = false) /** - * Sanitize a filename by removing anything besides A-Za-z0-9_.- + * Sanitize a filename by removing anything besides legit characters * * Intended usecase: - * When using a filename in a Content-Disposition header the value should not contain ; or " + * When using a filename in a Content-Disposition header the value + * should not contain ; or " + * + * When exporting, avoiding generation of an unexpected double-extension file * * @param string The filename + * @param boolean Whether to also replace dots * * @return string the sanitized filename * */ -function PMA_sanitize_filename($filename) { - $filename = preg_replace('/[^A-Za-z0-9_.-]/', '_', $filename); +function PMA_sanitize_filename($filename, $replaceDots = false) { + $pattern = '/[^A-Za-z0-9_'; + // if we don't have to replace dots + if (! $replaceDots) { + // then add the dot to the list of legit characters + $pattern .= '.'; + } + $pattern .= '-]/'; + $filename = preg_replace($pattern, '_', $filename); return $filename; }