PHP 上传临时文件名发生冲突

发布于 2024-07-15 00:44:44 字数 470 浏览 11 评论 0原文

当用户上传文件时,它会随机被另一个用户上传的文件替换,我最终找到了 PHP 的问题以及 tmp 文件名被重用。 有没有办法来解决这个问题? 有没有办法制作更好的随机名称? 它似乎随着时间的推移而退化,因为随机文件名种子变得更弱? 这是在 PHP 5.2.8 和 FreeBSD 7.0 上的

日志,显示如何使用相同的 tmp 文件名并被另一个上传覆盖: http://pastebin.com/m65790440

非常感谢任何帮助。 我已经尝试解决这个问题四个多月了,但随着时间的推移,情况变得更糟。 谢谢。

编辑:请记住,这不是 PHP 代码问题,这是在到达任何 PHP 代码之前发生的,通过 $_FILES['name']['tmp_name'] 接收的文件在接收和跟踪时不正确在到达上传处理脚本之前,它会被其他人的上传覆盖

When a user uploads a file, randomly it gets replaced by another user's upload, I've finally tracked down the issue to PHP and the tmp file name being reused. Is there a way to fix this? Is there a way to make better random names? It seems to degrade over time, as in the random file name seed gets weaker? This is on PHP 5.2.8 and FreeBSD 7.0

Here is a log showing how the same tmp file name gets used and is overwritten by another upload: http://pastebin.com/m65790440

Any help is GREATLY appreciated. I've been trying to fix this for over 4 months and has gotten worse over time. Thank you.

EDIT: Keep in mind that this is not a PHP code issue, this is happening before it reaches any PHP code, the file received via $_FILES['name']['tmp_name'] is incorrect when it is received and its been traced back that it is being overwritten with someone else's upload before it reaches the upload processing script

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

空城仅有旧梦在 2024-07-22 00:44:45

文件上传后将其移至用户目录。 应删除这些临时文件。

Move your files to a user dir after they have been uploaded. Those temp files should be removed.

盛夏尉蓝 2024-07-22 00:44:45

我建议使用 GUID 生成器来生成文件名,因为您会得到这么多文件名。

I would recommend using a GUID generator for the filename seeing that you are getting so many.

风情万种。 2024-07-22 00:44:44

追踪相关代码后 _gettemp 在 FreeBSD 7 的 libc 实现中,我不清楚文件 tmp_name 的内容如何可能无效。 (要跟踪它,您可以下载 PHP 5.2.8 的副本并读取 main/rfc1867.c - main/php_open_temporary_file.c 中的第 1018 行调用,该函数从第 227 行开始,它是从第 97 行开始的函数的主要工作,但是,它本质上只是系统上 mkstemp 的包装器,可以在 FreeBSD libc 实现 第 66 行(链接),它使用 _gettemp (同上)实际生成随机文件名然而,mkstemp 的手册页在 BUGS 部分提到arc4random() 函数< /a> 不可重入。 可能有可能有两个同时请求进入关键代码部分并返回相同的tmp_name - 我对 Apache 如何与 mod_php 或 php-cgi 一起工作知之甚少在那里发表评论(尽管使用 FastCGI/php-cgi 可能有效 - 我目前无法对此发表成功评论)。

但是,为了寻求最简单的解决方案,如果您没有完全遇到文件 tmp_name 本身无效的情况,而是与其他上传的文件发生冲突(例如,如果使用 tmp_name 的文件名部分作为唯一源)存储文件名的唯一性),您可能会因生日悖论而面临冲突。 在 另一个问题中,您提到有大约 5,000,000 个要移动的文件,并且在 还有一个问题中,您提到接收每天上传 30-40k 次。 在我看来,这是生日悖论碰撞的主要情况。 mktemp 手册页提到(如果使用六个“X”就像 PHP 那样)有 56,800,235,584 个可能的文件名(62 ** 6,或 62 ** n,其中 n = 'X' 的数量等)。 但是,鉴于您的文件数量超过 500 万个,发生冲突的概率为 大约 100% (另一个启发式表明您已经经历过 220 次碰撞, if ((files*(files-1))/2)/(62**6) 表示任何内容,其中 files = 5,000,000)。 如果这是您面临的问题(可能,如果没有向生成的上传文件名添加进一步的熵),您可以尝试类似 move_uploaded_file($file['tmp_name'], UPLOADS. sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.')) - 这个想法是为随机文件名添加更多随机性,防止冲突。 另一种方法是在 main/php_open_temporary_file.c 的第 134 行添加两个“X”并重新编译。

After chasing the relevant code down to _gettemp in FreeBSD 7's libc implementation, I'm unclear regarding how the contents of the file tmp_name could be invalid. (To trace it, you might download a copy of PHP 5.2.8 and read in main/rfc1867.c - line 1018 calls in main/php_open_temporary_file.c, the function starting on line 227, which does it's main work in the function starting on line 97, which, however, is essentially just a wrapper for mkstemp on your system, which is found in the FreeBSD libc implementation on line 66 (linked), which uses _gettemp (same as above) to actually generate the random filename. However the manpage for mkstemp mentions in the BUGS section that the arc4random() function is not reentrant. It might be a possibility that 2 simultaneous requests are entering the critical code section and returning the same tmp_name - I know too little about how Apache works with either mod_php or php-cgi to comment there (though using FastCGI/php-cgi might work - I can't comment successfully on this at this time).

However, aiming for the simpliest solution, if you are not quite experiencing the file tmp_name itself being invalid, but colliding instead with other uploaded files (for example, if using the filename portion of tmp_name as your only source of uniqueness in the stored filename), you could be facing collisions due to the birthday paradox. In another question you mention having some 5,000,000 files to move, and in still another question you mention recieving 30-40k uploads a day. This strikes me as a prime situation for a birthday paradox collision. The mktemp man page mentions that (if using six 'Xs' as PHP does) there are 56,800,235,584 possible filenames (62 ** 6, or 62 ** n where n = number of 'Xs', etc). However, given that you have more than some 5 million files, the probability of a collision is approximately 100% (another heuristic suggests you'll have already experienced some order of 220 collisions already, if ((files*(files-1))/2)/(62**6) means anything, where files = 5,000,000). If this is the problem you are facing (probable, if not adding further entropy to the generated uploaded filename), you might try something like move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.')) - the idea being to add more randomness to the random filename, preventing collisions. An alternative could be to add two more 'Xs' to line 134 of main/php_open_temporary_file.c and recompile.

提笔书几行 2024-07-22 00:44:44

听起来您的 PHP 安装或 PHP 内部用于生成随机文件名的系统调用有严重错误(很可能 tempnam)。

对于其他人:PHP 在处理用户代码之前在内部处理上传的文件。 这些名称存储在 $_FILES['file']['tmp_name'] 中(其中 'file' 是表单上文件输入元素的(带引号的)名称)。

It sounds like something is seriously wrong with either your PHP installation or whichever system call PHP is internally using to generate the random file names (most likely tempnam).

For everyone else: PHP handles uploaded files internally before the user code is ever processed. These names are stored in $_FILES['file']['tmp_name'] (where 'file' is the (quoted) name of the file input element on the form).

旧伤慢歌 2024-07-22 00:44:44

PHP 是否在 apache 下运行,如 mod_php

您可以尝试创建一个每个进程的临时上传目录,其名称包含你的 php getmypid(),然后 ini_set 你的 PHP 进程' upload_tmp_dir
那个目录。 如果为每个请求生成一个新的 php 进程,这将不起作用。

Is PHP running under apache, as mod_php?

You may try to create a per-process temporary upload directory whose name contains your php getmypid(), then ini_set your PHP process' upload_tmp_dir to
that directory. This will not work if a new php process is spawned for every request.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文