Index: INSTALL.txt
===================================================================
RCS file: /cvs/drupal/drupal/INSTALL.txt,v
retrieving revision 1.29.2.2
diff -u -p -r1.29.2.2 INSTALL.txt
--- INSTALL.txt 25 May 2006 01:34:20 -0000 1.29.2.2
+++ INSTALL.txt 1 Jun 2006 21:31:02 -0000
@@ -147,9 +147,14 @@ INSTALLATION
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
+ "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.74.2.1
diff -u -p -r1.74.2.1 file.inc
--- includes/file.inc 25 May 2006 01:34:20 -0000 1.74.2.1
+++ includes/file.inc 1 Jun 2006 21:31:03 -0000
@@ -113,17 +113,17 @@ function file_check_directory(&$director
}
if ((file_directory_path() == $directory || file_directory_temp() == $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);
}
}
-
return true;
}
Index: modules/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload.module,v
retrieving revision 1.100
diff -u -p -r1.100 upload.module
--- modules/upload.module 27 Apr 2006 19:32:54 -0000 1.100
+++ modules/upload.module 1 Jun 2006 21:31:03 -0000
@@ -195,9 +195,10 @@ function _upload_prepare(&$node) {
unset($_SESSION['file_current_upload']);
+ global $user;
+
// Save new file uploads to tmp dir.
if (($file = file_check_upload()) && user_access('upload files')) {
- global $user;
// Scale image uploads.
$file = _upload_image($file);
@@ -216,6 +217,11 @@ function _upload_prepare(&$node) {
// Attach file previews to node object.
if (is_array($_SESSION['file_previews']) && count($_SESSION['file_previews'])) {
foreach($_SESSION['file_previews'] as $fid => $file) {
+ if ($user->uid != 1) {
+ // Here something.php.pps becomes something.php_.pps
+ $file->filename = upload_munge_filename($file->filename, NULL, 0);
+ $file->description = $file->filename;
+ }
$node->files[$fid] = $file;
}
}
@@ -317,6 +323,11 @@ function _upload_validate(&$node) {
form_set_error('upload', t('The selected file %name can not be attached to this post, because the disk quota of %quota has been reached.', array('%name' => theme('placeholder', $file->filename), '%quota' => theme('placeholder', format_size($usersize)))));
$valid = FALSE;
}
+ elseif (strlen($node->files[$fid]->filename) > 255) {
+ form_set_error('upload', t('The selected file %name can not be attached to this post, because the filename is too long.', array('%name' => theme('placeholder', $munged_filename))));
+ $valid = FALSE;
+ }
+
if (!$valid) {
unset($node->files[$fid], $_SESSION['file_previews'][$fid]);
file_delete($file->filepath);
@@ -464,6 +475,66 @@ function upload_total_space_used() {
return db_result(db_query('SELECT SUM(filesize) FROM {files}'));
}
+/**
+ * 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) {
+ global $user;
+
+ $original = $filename;
+
+ // Allow potentially insecure uploads for very savvy users and admin
+ if (!variable_get('allow_insecure_uploads', 0)) {
+
+ 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 (!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) {
if (!is_array($node->files)) {
return;
@@ -551,14 +622,17 @@ function upload_delete_revision($node) {
}
function _upload_form($node) {
+
$form['#theme'] = 'upload_form_new';
if (is_array($node->files) && count($node->files)) {
$form['files']['#theme'] = 'upload_form_current';
$form['files']['#tree'] = TRUE;
foreach ($node->files as $key => $file) {
- $description = "". file_create_url((strpos($file->fid,'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path()))) ."";
+ $description = file_create_url((strpos($file->fid, 'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path())));
+ $description = "". check_plain($description) ."";
$form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description );
+
$form['files'][$key]['size'] = array('#type' => 'markup', '#value' => format_size($file->filesize));
$form['files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => $file->remove);
$form['files'][$key]['list'] = array('#type' => 'checkbox', '#default_value' => $file->list);