CVE-2013-3239: Improper Control of Generation of Code ('Code Injection') (CWE-94)
value: phpMyAdmin 3.5.x before 3.5.8 and 4.x before 4.0.0-rc3, when a SaveDir directory is configured, allows remote authenticated users to execute arbitrary code by using a double extension in the filename of an export file, leading to interpretation of this file as an executable file by the Apache HTTP Server, as demonstrated by a .php.sql filename.
CWE description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Published: 2013-04-26T03:34Z
Repository: https://github.com/phpmyadmin/phpmyadmin
Language: PHP
Files changed: export.php, libraries/sanitizing.lib.php
Commit date: 2013-04-24 08:09:13 -0400
Commit message: Security: block another case of remote execution vulnerability

Diff: diff --git a/export.php b/export.php
index 10567d1d1ad..6084cafc5f9 100644
--- a/export.php
+++ b/export.php
@@ -270,14 +270,14 @@ function PMA_exportOutputHandler($line)
         if (isset($remember_template)) {
             $GLOBALS['PMA_Config']->setUserValue('pma_table_filename_template',
                 'Export/file_template_table', $filename_template);
         }
     }
-    // remove dots in template to avoid a remote code execution vulnerability
-    $filename_template = str_replace('.', '', $filename_template);
     $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
     $extension_start_pos = strlen($filename) - strlen($export_list[$type]['extension']) - 1;
     $user_extension = substr($filename, $extension_start_pos, strlen($filename));
diff --git a/libraries/sanitizing.lib.php b/libraries/sanitizing.lib.php
index 1f3110f305e..111fdf38599 100644
--- a/libraries/sanitizing.lib.php
+++ b/libraries/sanitizing.lib.php
@@ -132,21 +132,32 @@ function PMA_sanitize($message, $escape = false, $safe = false)
     return $message;
 }
 
 
 /**
- * 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;
 }
 
 ?>

Vulnerable code:     // remove dots in template to avoid a remote code execution vulnerability
    $filename_template = str_replace('.', '', $filename_template);
    $filename = PMA_sanitize_filename($filename);
 * Sanitize a filename by removing anything besides A-Za-z0-9_.-
 *    When using a filename in a Content-Disposition header the value should not contain ; or "
function PMA_sanitize_filename($filename) {
    $filename = preg_replace('/[^A-Za-z0-9_.-]/', '_', $filename);
Fixed code:     // 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);
 * Sanitize a filename by removing anything besides legit characters 
 *    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   boolean Whether to also replace dots 
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);