>我在PHP中有一个简单的形式,可以将文件从XML转换为SQL,反之亦然。在这种形式中,有一个输入,用户可以在其中上传扩展名为 xml 或 sql 的文件。我做了各种检查(文件扩展名和文件大小),我使用全局数组 $_FILES 的值 tmp_name 读取文件,我为转换做了一些操作,然后将修改后的文件保存在我的服务器中(以 gz 格式压缩)在客户端计算机中文件的原始名称,以便将链接提供给用户并下载它。
我的问题是:我上面列出的步骤存在利用风险?一般来说,上传文件有被利用的风险?还是风险,在客户端计算机中上传具有原始名称的文件?
谢谢。
允许用户上传文件时总是存在被利用的风险,因此
最好担心。您说"我为转换做了一些操作",因此虽然我无法具体评论此操作的安全性,但根据操作和提供给它的内容(例如缓冲区溢出,无效数据),这里可能存在风险。
我假设您正在使用.gz扩展名保存文件。
如果根本不清理文件名,使用客户端文件名保存可能会带来兼容性问题。文件系统之间不允许(或有问题的)字符存在差异,例如Unix中的&或Windows上的:。有时,如果您只是保存一个文件,然后简单地再次读取它,您的代码将无法"找到"它,除非您正确转义或去除所有这些字符。
例如,如果客户端文件名可能嵌入其中的路径,则客户端文件名可能会带来风险。呈现的文件名,例如"../../../../home/user/file"可能会诱使您的程序覆盖文件,只要权限实现得非常糟糕并且您只是连接路径。在最坏的情况下,我会说这将是一个烦恼或 DoS 攻击 - 仅限于覆盖 gzip 文件并"破坏"它们。
客户端文件名可能会覆盖其他用户的文件?我不确定您的命名空间是什么,但是一个聪明的攻击者可能会尝试通过巧妙地命名来诱骗其他用户下载他们的 xml/sql 文件。
此外,如果您可以猜到其他人的文件名,则可以猜测生成的URL,并通过它们寻找内容。
如果使用漂亮的 GUID 来命名文件,所有这些风险都会消失。或者将其映射到每个用户的会话(例如 file1.gz仅对该用户的会话有效)。
我通常不使用客户端名称,或者在重新呈现它们之前认真验证和清理它们。
使用 php(事实上,还有其他解释性语言)上传文件的主要风险是用户可以上传.php
文件,如果它存储在 web-root 中,则执行它。
从您的问题来看,您似乎只允许某些非.php
扩展。请确保在服务器端执行此检查,而不仅仅是在客户端上。此外,如果您之后不需要在网络上提供上传的文件,请将其存储在您的网络根目录之外。如果您在上传后强制使用文件名和扩展名(不保留原始文件名和扩展名),那么您可以更好地控制系统中发生的事情。
其他文件类型也可能被利用(例如图像,请参阅 https://imagetragick.com/),因此最好专门检查您想要上传的文件类型。