已关闭,此问题需要更focused。目前不接受答复。
**想改善这个问题吗?**更新问题,使其仅通过editing this post关注一个问题。
两年前关闭。
Improve this question
为了保护我们正在编程的网站免受SQL注入或XSS等攻击,我们需要在存储或显示用户的输入之前对其进行过滤。
在PHP中,我们使用htmlspecialchars
和addslashes
函数来防止XSS和SQL-Injection攻击。那么,那些文件呢?
我曾经通过检查文件类型和扩展名来保护网络应用程序,以了解这些文件是否在白名单中。但是我不使用htmlspecialchars
和addslashes
函数,因为我没有看到有人使用这种方法。
例如,如果我想获取使用$_FILES['file']['tmp_name']
的文件名,那么我将其直接存储到数据库中。
这是错误的,还是它不能注入代码,命令。..等等
3条答案
按热度按时间c0vxltue1#
简短回答:不,它只是一堆字符串值,仅此而已。
长回答:
我曾经通过检查文件类型和扩展名来保护网络应用程序,以了解这些文件是否在白名单中。
这是一个很好的方法,如果正确应用和执行。
$_ FILES数组只是一个 * 载体 。它本身不能被滥用,但你必须 * 信任 * 它所携带的东西-即信任正在传递给服务器/由服务器传递的文件。
当我写下这个答案的时候;下面;似乎OP对他们实际上在保护什么以及为什么感到困惑:
OP称之为“最佳实践”( 绝对不是 ):
如果你想使用$_ FILES ['file '] ['tmp_name']来存储到你的数据库中或者显示在你的UI中,你应该使用addslashes或者PDO prepare语句来保护你免受SQL-Injection攻击。
这是对
$_FILES
数组填充方式的误解。$_FILES['file']['tmp_name']
的值是由服务器**设置的,而不是由用户或客户端设置的。用户给定的值为:
将文件存储在数据库中是not usually a good idea,并且在数据库安全性方面有自己的缺陷,dhnwebpro has their own answer。
$_FILES['file']['tmp_name']
是临时存储空间中文件的服务器位置。PHP Manual明确指出:
默认情况下,文件将存储在服务器的默认临时目录中,除非php中的upload_tmp_dir指令指定了另一个位置。服务器的默认目录可以通过在PHP运行的环境中设置环境变量TMPDIR来更改。
如果该文件没有被移走或重命名,则将在请求结束时从临时目录中删除。
$_FILES['file']['tmp_name']
值被滥用了,那么这是服务器妥协的迹象,你的盘子里有一大堆麻烦,远远超过了恶意的文件上传。*那么,如何审核携带的文件?
有许多类型的文件攻击,这个主题远远超出了您所问的范围。比如说;真正的JPEG图像可以在JPEG元数据中包含XSS脚本,但当加载和查看JPEG时会触发此XSS,但对于未专门检查此漏洞 * 的外部观察者 * 而言,JPEG文件并非“坏文件”或XSS文件。
那么,你是阻止这个
file.jpg
还是阻止 * 所有 * Jpeg文件?这是一个艰难的决定,但在PHP中有一些非常好的工作方法(我相信这也超出了这个问题的范围)。简而言之,你的问题可以做一些编辑和澄清,你到底想保护什么,你愿意走多远达到保护水平。我可以给你一个粗略的全面指导,以防止某些 * MIME文件类型 * 被接受到您的服务器上。这看起来和感觉像你想要的,一些东西来阻止偷偷摸摸的MP4视频被上传为文档文件(反之亦然)。
一:
忽略文件名(
$_FILES['file']['name']
)。* * 切勿**信任用户数据。二:
忽略声明的文件类型(
$_FILES['file']['type']
)。任何给定MIME类型的文件名(如.pdf
)都应该被忽略。* * 切勿**信任用户数据。三:
使用PHP
Finfo
函数集作为初步指标。它是**不完美,但会抓住大多数东西。4:图片:
如果你正在检查上传的图像,最好的方法是按照3检查
finfo
文件类型,然后让PHP将图像加载到空白画布中并重新保存图像,从而剥离所有多余的元数据和其他可能不需要的非图像数据数据。Like this method: Remove exif data from jpg using php。
五:
另外,建议您始终为上传的文件指定随机名称,永远不要使用
$_FILES['file']['name']
值。六:
根据您试图避免和/或中和的威胁类型,您可以打开上传的文件并读取文件的前几个字节,并将其与该类型白名单文件中确认的字节进行比较。这是相当微妙的,再次超出了这个答案的范围,这个答案已经足够长了。
sq1bmfud2#
有一个函数is_uploaded_file来确定文件确实是一个上传的文件,而不是用户对文件路径的某种操作。据我所知,
is_uploaded_file($_FILES['file']['tmp_name'])
不可能返回false。您还应该检查filesize($_FILES['file']['tmp_name'])
是否小于要插入的列的大小。至于“直接存储到数据库”,你仍然需要practice good SQL injection prevention文件内容。此外,通常很难扩展在数据库中存储文件的解决方案,但这是一个您可能已经考虑过的单独问题。
w8rqjzmb3#
如果你使用的是PDO或者MySQLi,你应该能够将文件放在一个准备好的语句中,这样可以保护你免受SQL注入攻击。我从https://www.mysqltutorial.org/php-mysql-blob/中粘贴了一个方法,它有一些关于在MySQL数据库中存储文件的好信息。
或者,您可以将文件存储在文件系统中,并在需要提供文件时包含对该文件的引用。这种方法更快,但不方便将所有数据保存在一个地方。
关于
$_FILES
数组元素的细节有点隐藏在手册中,但可以在示例1的末尾找到:https://www.php.net/manual/en/features.file-upload.post-method.php
$_FILES
数组的所有元素上的值应被视为用户输入。我建议忽略这些价值观。但是,如果您希望将它们写入数据库和/或稍后在UI中显示,您肯定需要保护自己免受SQL注入和XSS攻击。因此,在这种情况下,使用预处理语句和htmlspecialchars
不会有什么坏处。