有没有办法通过文件类型限制目录内容?
例如,我有一个上传目录,我只希望用户将图像放入其中,我可以更进一步并实际上设置一个仅允许其中包含图像的限制吗?
我想过用 CRON 作业来检查文件扩展名,但想知道是否还有另一种方法......
答案1
尝试使用 cron 作业或类似的“事后”强制执行此操作存在许多问题:
比赛条件。无论您使用哪种方法,如果您有一些程序或代码将遍历目录并可能拾取并使用您不希望其与之交互的文件,那么实际的唯一方法是防止这样做的目的是(1)以这种方式进行编码(或者修改现有的源代码,如果它是开源的);或 (2) 不允许将文件放置在该目录中首先。
您没有说明您正在运行哪个操作系统,但在 Linux 上,您可以在某种程度上有效地用于
fanotify
监视目录中的文件创建/重命名,并在创建不允许的文件或将其重命名为不允许的名称或内容时采取措施。当然,这本质上是一种竞争条件,因此,如果您有其他代码将访问该目录,而“用户”(其他程序或用户帐户)将文件放入其中,则您不可能绝对阻止这些文件以免被拾取(并且可能在您的代码有机会删除/移动它们之前被读取)。
我的建议是这样的:
创建一个新组,或使用现有组,该组的唯一成员是您信任的用户,这些用户不会运行任何将不需要的文件放入该目录中的程序。
将目录的权限设置为 770 或 775 等,并分别使用
chmod
和适当设置组和用户所有者chown
。这将阻止该组之外的用户访问(或写入)该目录,因此您不信任在其中放置正确文件的程序/用户将被排除在外文件系统的自主访问控制机制。这应该适用于几乎所有类似 UNIX 的系统(甚至是 Windows,但权限系统略有不同)。只需确保您没有将此目录存储在 ntfs-3g 或其他忽略任意访问控制的文件系统上即可。编写一个提供服务(Web 服务、UNIX 域套接字或某物)将接受文件内容以及“上传”的文件名。然后,该程序应该从用户接收整个文件,将其存储在 RAM 或临时文件夹中,直到完全下载,然后检查文件名和内容,以确保不需要的文件类型的文件会引发错误,并且不会被放置在目录中。如果文件显示正常,您可以将文件内容写入上述受组限制目录中所需的文件名。
对于上一段的“使用现有程序”组件,我用谷歌搜索了一下,只能找到一个可能的解决方案(而且它甚至不是很强大):Samba支持文件扩展名黑名单。但是,您应该知道,任何具有任意内容的文件都可以重命名为包含任何文件扩展名,以轻松绕过文件扩展名检查。文件扩展名检查对于防止用户意外激活可执行文件很有用(例如;如果您上传了一个名为 .txt 的可执行文件,它将在用户的文本编辑器中无害地打开,最糟糕的后果是冻结文本编辑器,因为文件太大;然而,如果他们以扩展名 .exe 上传文件,则在 Windows 上双击就会出现跑步文件)。
但仅靠文件扩展名检查并不能确保内容文件的类型是所需的类型(或不是的一个不受欢迎的类型)。为此,您需要某种钩子来“在文件上传时”调用自定义代码,例如在 FTP 服务器中(我不知道有任何 FTP 服务器可以通过这种方式扩展,超出我的想象) -- 然后file
对结果调用例如 UNIX 实用程序以查看它是否属于不需要的类型。file
不是刀枪不入,但它非常善于识别内容文件的名称,无论其名称如何。
我要留给您思考的最后一件事是:如果您不看表面,那么禁止不受欢迎的文件内容的问题就会大得多。例如,假设您从 PDF 文档开始。现在,翻转该 PDF 文档中的一位,使该文件的格式现在违反 PDF 标准。如果您在“简单”的 PDF 阅读器中打开此文件,它将因文件格式被破坏而无法打开。但是,如果您在“智能”PDF 阅读器中打开它,可能能够自动检测并修复损坏!如果损坏足够严重,您的文件类型检测程序可能会误认为它甚至不是 PDF 文档。但最终用户可能仍然能够打开该文件。
更糟糕的是,如果你想压制为了防止传输特定文件内容或文件类型,用户可以通过无数种方法来绕过它。一种方法是故意破坏文件头使其无法识别,这样您的黑名单就无法识别文件类型,从而默认允许它通过;或者,如果您有白名单,则将该文件伪装成某个文件的有效文件格式允许类型,但然后让内容包含实际的有效负载。一对合作的用户(或远程控制另一个用户的攻击者)可以上传然后下载该文件,将接收端的内容更改为所需的格式,然后使用该数据。
这涉及到隐写术领域,您可以使用已灭绝的剑龙 DNA 来尝试确定文件是否属于给定类型;-)(开玩笑;剑龙与隐写术无关:))。在隐写术中,文件表面上看起来完全合法,甚至可以被白名单过滤器允许;但攻击者可以与其他用户合作,通过将任意数据隐藏在现有文件看似有效的数据中来传输任意数据(以任何文件格式)。隐写术很难被发现。
但是,如果您的目的只是阻止“快乐路径”文件类型,即文件公开且公然地声明自己属于特定类型,则可以对file
允许通过 FTP 上传到的暂存目录中的文件使用类似的操作,然后,如果文件根据您的测试“签出”,您可以将其移至受限目录。这将非常有效地防止未受过加密/隐写术培训的用户将不需要的文件类型上传到您的系统。