Index: INSTALL.txt
===================================================================
RCS file: /cvs/drupal/drupal/INSTALL.txt,v
retrieving revision 1.17.2.4
diff -u -p -r1.17.2.4 INSTALL.txt
--- INSTALL.txt 25 May 2006 01:34:05 -0000 1.17.2.4
+++ INSTALL.txt 1 Jun 2006 20:27:13 -0000
@@ -189,12 +189,17 @@ INSTALLATION
by the Drupal server process. You can change the name of this
subdirectory at "Administer > Settings > File system settings".
- SECURITY NOTICE: Certain Apache configurations can be vulnerable
- to a security exploit allowing arbitrary code execution. Drupal
- will attempt to automatically create a .htaccess file in your
- "files" directory to protect you. If you already have a .htaccess
- file in that location, please add the following line:
- SetHandler This_is_a_Drupal_security_line_do_not_remove
+ SECURITY NOTICE: Certain Apache configurations can be vulnerable
+ to a security exploit allowing arbitrary code execution. Drupal
+ will attempt to automatically create a .htaccess file in your
+ "files" directory to protect you. If you already have a .htaccess
+ file in that location, please add the following lines:
+
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+ Options None
+
+ RewriteEngine off
+
You can now launch your browser and point it to your Drupal site.
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.39.2.13
diff -u -p -r1.39.2.13 file.inc
--- includes/file.inc 25 May 2006 01:34:05 -0000 1.39.2.13
+++ includes/file.inc 1 Jun 2006 20:27:16 -0000
@@ -106,13 +106,14 @@ function file_check_directory(&$director
}
if ((variable_get('file_directory_temp', FILE_DIRECTORY_TEMP) == $directory || variable_get('file_directory_path', 'files') == $directory) && !is_file("$directory/.htaccess")) {
- if (($fp = fopen("$directory/.htaccess", 'w')) && fputs($fp, 'SetHandler This_is_a_Drupal_security_line_do_not_remove')) {
+ $htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\n\n RewriteEngine off\n";
+ if (($fp = fopen("$directory/.htaccess", 'w')) && fputs($fp, $htaccess_lines)) {
fclose($fp);
}
else {
- $message = t("Security warning: Couldn't write .htaccess. Please create a .htaccess file in your %directory directory which contains the following line: SetHandler This_is_a_Drupal_security_line_do_not_remove", array('%directory' => $directory));
+ $message = t("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: %htaccess", array('%directory' => theme('placeholder', $directory), '%htaccess' => '
'. str_replace("\n", '
', check_plain($htaccess_lines))));
form_set_error($form_item, $message);
- watchdog('file system', $message, WATCHDOG_ERROR);
+ watchdog('security', $message, WATCHDOG_ERROR);
}
}
Index: modules/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload.module,v
retrieving revision 1.31.2.10
diff -u -p -r1.31.2.10 upload.module
--- modules/upload.module 20 Feb 2006 17:24:57 -0000 1.31.2.10
+++ modules/upload.module 1 Jun 2006 20:27:17 -0000
@@ -179,6 +179,11 @@ function upload_nodeapi(&$node, $op, $ar
// Don't do any checks for uid #1.
if ($user->uid != 1) {
+ // here, something.php.pps becomes something.php_.pps
+ $munged_filename = upload_munge_filename($file->filename, NULL, 0);
+ $file->filename = $munged_filename;
+ $file->description = $munged_filename;
+
// Validate file against all users roles. Only denies an upload when
// all roles prevent it.
foreach ($user->roles as $rid => $name) {
@@ -211,6 +216,9 @@ function upload_nodeapi(&$node, $op, $ar
elseif ($error['usersize'] == count($user->roles) && $user->uid != 1) {
form_set_error('upload', t('Error attaching file %name: exceeds maximum file size', array('%name' => theme('placeholder', $file->filename))));
}
+ elseif (strlen($munged_filename) > 255) {
+ form_set_error('upload', t('The selected file %name can not be attached to this post, because the filename is to long.', array('%name' => theme('placeholder', $munged_filename))));
+ }
else {
$key = 'upload_'. count($_SESSION['file_uploads']);
$file->source = $key;
@@ -321,6 +329,69 @@ function upload_count_size($uid = 0) {
return db_result($result);
}
+/**
+ * Munge the filename as needed for security purposes.
+ *
+ * @param $filename
+ * The name of a file to modify.
+ * @param $extensions
+ * A space separated list of valid extensions. If this is blank, we'll use
+ * the admin-defined defaults for the user role from upload_extensions_$rid.
+ * @param $alerts
+ * Whether alerts (watchdog, drupal_set_message()) should be displayed.
+ * @return $filename
+ * The potentially modified $filename.
+ */
+function upload_munge_filename($filename, $extensions = NULL, $alerts = 1) {
+
+ $original = $filename;
+
+ // Allow potentially insecure uploads for very savvy users
+ if (!variable_get('allow_insecure_uploads', 0)) {
+
+ global $user;
+
+ if (!isset($extensions)) {
+ $extensions = '';
+ foreach ($user->roles as $rid => $name) {
+ $extensions .= ' '. variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps'));
+ }
+
+ }
+
+ $whitelist = array_unique(explode(' ', trim($extensions)));
+
+ $filename_parts = explode('.', $filename);
+
+ $new_filename = array_shift($filename_parts); // Remove file basename.
+ $final_extension = array_pop($filename_parts); // Remove final extension.
+
+ foreach($filename_parts as $filename_part) {
+ $new_filename .= '.'. $filename_part;
+ // if the extension is not allowed and contains 2-5 characters followed
+ // by an optional digit, then it's potentially harmful, so we add an _
+ if (!in_array($filename_part, $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) {
+ $new_filename .= '_';
+ }
+ }
+ $filename = "$new_filename.$final_extension";
+ }
+
+ if ($alerts && $original != $filename) {
+ $message = t('Your filename has been renamed to conform to site policy.');
+ drupal_set_message($message);
+ }
+
+ return $filename;
+}
+
+/**
+ * Undo the effect of upload_munge_filename().
+ */
+function upload_unmunge_filename($filename) {
+ return str_replace('_.', '.', $filename);
+}
+
function upload_save($node) {
foreach ((array)$node->files as $key => $file) {
if ($file->source && !$file->remove) {