【问题标题】:Drupal Filefield won't upload javascript files?Drupal Filefield 不会上传 javascript 文件?
【发布时间】:2009-09-04 09:46:58
【问题描述】:

我有一个网站,其中个别页面可能需要一些 javascript 或 CSS 文件。在管理此过程时,我试图将所有内容都保留在客户端,而不是访问 FTP 并在代码中整理所有内容,因此我需要能够上传 css 和 js 文件。

我已经启动并运行了 CCK 文件域,它适用于 css 文件,但它拒绝上传 .js 文件。相反,它似乎将每个 .js 视为“.js.txt”,然后该文件在服务器上显示为 thisismyfile.js.txt

不理想...

有谁知道如何解决这个问题。是 Drupal 或服务器的 mime 类型问题,还是 Drupal 设置为避免脚本上传和 n00b 黑客攻击。

文件上传后,我打算在页面或节点上使用 PHP 模式调用 drupal_add_cssdrupal_add_js

【问题讨论】:

  • 猜测是安全问题。

标签: javascript drupal drupal-6 drupal-files


【解决方案1】:

查看filefield模块中field_file.inc中的field_file_save_file()函数,可以发现如下sn -p

// Rename potentially executable files, to help prevent exploits.
if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
  $file->filemime = 'text/plain';
  $file->filepath .= '.txt';
  $file->filename .= '.txt';
}

所以是的,正如 Jeremy 猜想的那样,这是一个“安全问题”。

可以为该 RegEx 打补丁以立即“修复”,但这将完全删除对站点上使用的所有文件字段的这种原本有用的安全检查。

因此,更具体的解决方法可能是更好的方法。既然您想通过代码中的drupal_add_js() 调用添加文件,您不妨在那里重命名,添加某种验证以确保您可以“信任”文件(例如,谁上传了它,无论如何)。


编辑:关于调用drupal_add_js()时重命名(和替代)的选项:

  • 要重命名文件,请查看file_move() 函数。这样做的一个问题是它不会更新文件表中的相应条目,因此如果移动操作成功,您也必须这样做。 (文件字段只存储文件表中相应条目的“fid”,因此您需要通过“fid”在那里找到它并根据您的重命名更​​改“文件名”、“文件路径”和“文件mime”条目/移动)
  • 或者,您可以只加载 *.js.txt 文件的内容并使用 drupal_add_js() 的“内联”选项添加该字符串。这将不那么“优雅”,并且可能会影响性能,但如果在您的特定情况下这些不是重要标准,那么麻烦就会减少。
  • 另一种选择是只将 *.js.txt 文件按原样传递给 drupal_add_js(),忽略“错误”扩展名。一个简短的本地测试表明这是有效的(至少在 Firefox 中)。这可能是“最省力”的解决方案,但需要对不同浏览器行为进行一些额外的测试,这些行为涉及“错误命名”的 js 文件的使用。

【讨论】:

  • 咳咳,是的,很明显(并且明确提到了!)——这就是为什么我将 could 用斜体字表示并推荐了一种更具体的方法。我将进行编辑以澄清这一点。
  • 太好了,谢谢!正如我上面所说,注册将被禁用,只有管理员帐户才能上传文件,所以我愿意承担安全风险。为我指点代码干杯:D
  • 等等.. 我喜欢你在 drupal_add_js() 函数中重命名文件的想法。你能详细说明如何做到这一点吗?谢谢!
  • 好吧,要重命名文件,请查看file_move() 函数(Drupal API)。问题是这不会更新文件表中的相应条目,因此如果移动成功,您也必须这样做。 (filefield 只是将相应条目的 'fid' 存储在 files 表中,因此您需要通过 'fid' 找到它并根据您的重命名更​​改 'filename'、'filepath' 和 'filemime' 条目/移动)
  • 或者,您可以只加载 *.js.txt 文件的内容并使用 drupal_add_js 的“内联”选项添加该字符串。这将不那么“优雅”,并且可能会影响性能,但如果在您的特定情况下这些不是重要标准,那么麻烦就会减少。
【解决方案2】:

允许 Drupal 上传 javascript 文件会带来安全风险,这也是它不允许您这样做,而是附加 .txt 扩展名的原因。原因是js文件与php、pl、py、cgi、asp一起可执行。因此,如果 Drupal 可以将这些文件上传到服务器,那么作恶者就有可能上传一个文件并在您的服务器上运行它做各种令人讨厌的事情,基本上一切皆有可能。最好的办法是找到一种不同的安全上传文件的方式。

【讨论】:

  • 事情是 - 如果有人破解我的管理密码,我会比“他们可能会上传脚本”更担心。例如删除我的数据库.. 该网站不会对普通用户开放注册或做任何事情,注册将被禁用。
  • 如果他们破解了你的管理员通行证,他们只能访问一个站点,如果他们上传并执行一个 js 文件,他们可以删除整个服务器,更改 root 密码并“超越”服务器。就像我说的,他们几乎可以做任何事情。那就是他们可以做任何javascript可以做的事情,因为它是一种编程语言。
【解决方案3】:

我有类似的需求,并找到了一种绕过安全性的方法,首先通过在 hook_install 中运行这行代码来更改“allow_insecure_uploads”变量值:

 variable_set('allow_insecure_uploads', 1);

然后在一个模块中添加这个函数

/**
 * Implementation of FileField's hook_file_insert().
 */
function MODULE_NAME_file_insert(&$file) {
  //look for files with the extenstion .js.txt and rename them to just .js
  if(substr($file->filename, -7) == '.js.txt'){
  $file_path = $file->filepath;
  $new_file_path = substr($file_path, 0, strlen($file_path)-4);
  file_move($file_path, $new_file_path);

  $file->filepath = $file_path;
  $file->filename = substr($file->filename, 0, strlen($file->filename)-4);
  $file->filemime = file_get_mimetype($file->filename);
  $file->destination = $file->filepath;
  $file->status = FILE_STATUS_TEMPORARY;
  drupal_write_record('files', $file);
}

它的作用是在 hook_insert 调用中检查文件是否具有扩展名“.js.txt”。如果是,则将其复制到新位置并重命名。这是在安全检查之后,所以没关系。只要您不将它们放在 files/js 目录中,我认为您无需担心缓存清除删除您的 js 文件。为你的模块创建你自己的目录,你应该没问题。

【讨论】:

    【解决方案4】:

    当我想允许为特定字段按原样上传 .js 文件(不带 .txt 和“应用程序/javascript”mimetype)时,我遇到了这种情况。另外,我不想改变 Drupal 核心……当然。

    所以我需要创建一个实现 hook_file_presave() 的模块。这也适用于 Multiupload File Widget,因为它的挂钩位于 file_save()

    请注意,您必须将 MYMODULE_NAMEMYFIELD_NAME 替换为您自己的值。

    function MYMODULE_NAME_file_presave($file) {
    
        // Bypass secure file extension for .js for field_additional_js field only
        if((isset($file->source) && strpos($file->source, "MYFIELD_NAME") !== FALSE) && substr($file->filename, strlen($file->filename) - 7) == ".js.txt") {
    
            // Define new uri and save previous
            $original_uri = $file->uri;
            $new_uri = substr($file->destination, null, -4);
    
            // Alter file object
            $file->filemime = 'application/javascript';
            $file->filename = substr($file->filename, null, -4);
            $file->destination = file_destination($new_uri, FILE_EXISTS_RENAME);
            $file->uri = $file->destination;
    
            // Move fil (to remove .txt)
            file_unmanaged_move($original_uri, $file->destination);
    
            // Display message that says that
            drupal_set_message(t('Security bypassed for .js for this specific field (%f).', array('%f' => $file->filename)));
        }
    }
    

    【讨论】:

      【解决方案5】:

      Drupal 也“munges” javascript 文件。为了防止 Drupal 自动在文件名中添加下划线,在文件名被“munged”之前检查了一个隐藏变量。

      将变量设置为 1 为我解决了这个问题(同时更改了 include/file.inc 中的 REGEX)。

      我讨厌破解内核,但这对我来说似乎是一个糟糕的设计。 Javascript 文件不是像 php、py、pl、cgi 和 asp 这样的服务器端脚本。

      您可以使用允许的文件扩展名设置来防止上传 php 和其他服务器端脚本。

      例如:

      variable_set('allow_insecure_uploads', 1);

      见: http://api.drupal.org/api/function/file_munge_filename/6

      【讨论】:

      • 是的,恐怕就是这样!最后我的问题解决了,因为需要配置和上传脚本并且没有 FTP 访问权限的用户数量为零!
      【解决方案6】:

      因此,将 .js 文件上传到 files 目录几乎是不可能的。

      即使您设法干净地上传了 .js 文件,这些文件也会在缓存被清除时被删除。

      只要执行 drupal_clear_js_cache() 函数,文件目录中的任何 js 文件都会被删除。

      http://api.drupal.org/api/function/drupal_clear_js_cache/6

      所以 Drupal 将文件上传目录中的 .js 文件视为临时文件。

      现在我明白他们为什么要附加“.txt”了,这是为了防止它们在缓存被清除时被删除。

      因此,作为一种折衷方案,我想我将手动(通过 FTP)将 .js 文件上传到 /misc 文件夹。 :(

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-28
        • 2019-12-04
        • 2021-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-18
        相关资源
        最近更新 更多