如何防止用户猜测上传文件的 URL?
How can I prevent users from guessing uploaded file URLs?
我有一个简单的 upload/retrieval 脚本可以从我的数据库中检索图像。当我上传文件时,脚本将它们存储在 upoadsFolder/
中。当我想显示检索图像时,我使用以下代码:
<?php
include('./dbconn.php');
$q=$dbconnection->query('SELECT * FROM img_table WHERE id=7');
$row=$q->fetch();
$row['imgpath'];
echo "<img src=uploadsFolder/$row['imgpath'] />";
但如果用户知道或可以预测我的任何图像名称,例如 nameX.png
他将通过修改 HTML <img>
标签轻松查看这些图像:<img src=uploadsFolder/nameX.png />
.
我如何保护 uploadsFolder/
以防止这种情况发生?
MOREOVER : 如果只有他在 his/here 浏览器中输入 URL: " localhost/uploadimages/uploads/ "
!!!见附件!
既然要显示它们,就需要将它们放在某个地方public。但是,您可以使用哈希(id+时间戳的 md5)将它们存储在数据库中。这样一来,名字就无法预测了。
基本上唯一的方法就是让它变得不可预测。您可以将它们保存为 md5(id),但如果有人了解该算法,这仍然会使它们有点可预测。
如果用户可以列出目录,那你显然已经输了。
一般来说,依赖秘密名称 and/or 链接而不是实施访问控制是不好的做法。这些秘密往往会以各种方式泄露。例如,有一个 look at what happened to DropBox.
当人们尝试这样的事情时,安全性经常失败的另一种方式是使用可预测的随机性而不是密码随机性来导出秘密。 PHP Mersenne Twister 随机数生成器是可预测的:知道一些输出(即从允许用户知道的图像)将允许用户导出未来的输出(未来图像链接)和以前的输出(图像链接已经在那里了)。 PHP's lcg_value.
也是如此
底线:正确的访问控制是无可替代的。否则,您将违反 complete mediation security principle, which makes you vulnerable to direct object reference vulnerabilities.
"MOREOVER : The user also will be able to view whole content of my '
'uploadsFolder/' contents if Only he typed in his/here browser the
URL: " localhost/uploadimages/uploads/ " !!! See the attached !"
如果您不希望这种情况发生,那么您应该在您的站点上创建一个 .htaccess 文件并在其中包含以下内容:
RewriteEngine on
<ifModule mod_rewrite.c>
Options -Indexes
</IfModule>
这会限制对您网站上任何文件夹的访问,而没有完整的 link 到 document/file/image,等等,他们将收到 403 禁止访问错误消息。
只需将文件另存为.htaccess
另外,不要将图像保存在数据库中,只需保存文件名,然后将图像上传到上传文件夹,然后就会有类似的东西:
<img src="uploads/<?php echo $row['image_name']; ?>">
这样一来,如果用户可以访问您的数据库(顺便说一句,那是您的错),他们所能访问的只是文件名,而不是实际图像。
你也可以试试@heXer说的。创建一个系统,只有当用户登录时,他们才能查看图像,否则显示错误消息或将他们重定向到另一个页面。
执行以下操作将解决您的问题:
将图像文件存储在隐蔽的地方,例如 public_html
区域中的目录文件夹结构。在此父文件夹中,您可以使用 htaccess 和 simply deny all access to the files 防止热链接。 (存储在 public html 区域内比存储在 html 区域外更安全)。
# htaccess full file:
Options -Indexes
Deny from all
使用PHP文件来引用您要显示的图像;例如:
echo "<img src='uploadsFolder/showImage.php?img=".$row['imghash']."' />";
上面引用的 PHP 文件 - “showImage.php” - 然后可以在数据库中搜索这个唯一的哈希列。一旦找到,PHP 文件就会使用 file_get_contents()
to load the image and then output this image to the <img>
link with the appropriate headers.
将散列列添加到现有数据并填充它 (generate random strings). Ensure it is indexed as unique.
结果
图像文件应不与PHP图像显示文件存储在同一文件夹中。该文件夹不仅包含您的 PHP 文件。显然,为了方便起见,您可以更改此文件夹的位置(例如:/imageToucher/showImage.php?img=".$row['imghash']."
等),或者您可以使用 quick universal find and replace 更新 MySQL 中的图像文件路径。
现在每次您想加载任何受保护的文件时;您只需调用 PHP 文件,让它完成检查数据库的散列、获取关联的文件路径、从该路径抓取文件、加载它、解析它然后将其作为输出输出的工作PHP 文件本身。
此方法的好处
- 您的源文件路径永远不会被泄露。
- 您可以通过 PHP 中的
sleep()
语句快速限制(延迟)试图查找不存在文件的人,因此循环使用不同 $_GET['img']
值的人速度会很快变慢(您可以使用会话或 IP 跟踪器或类似工具来记录加载图像 URL 的失败尝试次数)
- PHP 文件可以处理找到的任何有效图像,因此您可以按缩略图大小显示图像,或根据需要设置其他输出标准。
一个小缺点可能是此文件夹中的数据需要通过网站另一部分的代码进行解析才能显示,因为 .htaccess
将拒绝所有直接访问,这包括网页中的引用,因此访问必须通过 PHP 和数据库来收集有效的 URL。这会使缩略图列表等在繁忙的场景中处理器负担更大且效率更低。
我有一个简单的 upload/retrieval 脚本可以从我的数据库中检索图像。当我上传文件时,脚本将它们存储在 upoadsFolder/
中。当我想显示检索图像时,我使用以下代码:
<?php
include('./dbconn.php');
$q=$dbconnection->query('SELECT * FROM img_table WHERE id=7');
$row=$q->fetch();
$row['imgpath'];
echo "<img src=uploadsFolder/$row['imgpath'] />";
但如果用户知道或可以预测我的任何图像名称,例如 nameX.png
他将通过修改 HTML <img>
标签轻松查看这些图像:<img src=uploadsFolder/nameX.png />
.
我如何保护 uploadsFolder/
以防止这种情况发生?
MOREOVER : 如果只有他在 his/here 浏览器中输入 URL: " localhost/uploadimages/uploads/ "
!!!见附件!
既然要显示它们,就需要将它们放在某个地方public。但是,您可以使用哈希(id+时间戳的 md5)将它们存储在数据库中。这样一来,名字就无法预测了。 基本上唯一的方法就是让它变得不可预测。您可以将它们保存为 md5(id),但如果有人了解该算法,这仍然会使它们有点可预测。
如果用户可以列出目录,那你显然已经输了。
一般来说,依赖秘密名称 and/or 链接而不是实施访问控制是不好的做法。这些秘密往往会以各种方式泄露。例如,有一个 look at what happened to DropBox.
当人们尝试这样的事情时,安全性经常失败的另一种方式是使用可预测的随机性而不是密码随机性来导出秘密。 PHP Mersenne Twister 随机数生成器是可预测的:知道一些输出(即从允许用户知道的图像)将允许用户导出未来的输出(未来图像链接)和以前的输出(图像链接已经在那里了)。 PHP's lcg_value.
也是如此底线:正确的访问控制是无可替代的。否则,您将违反 complete mediation security principle, which makes you vulnerable to direct object reference vulnerabilities.
"MOREOVER : The user also will be able to view whole content of my ' 'uploadsFolder/' contents if Only he typed in his/here browser the URL: " localhost/uploadimages/uploads/ " !!! See the attached !"
如果您不希望这种情况发生,那么您应该在您的站点上创建一个 .htaccess 文件并在其中包含以下内容:
RewriteEngine on
<ifModule mod_rewrite.c>
Options -Indexes
</IfModule>
这会限制对您网站上任何文件夹的访问,而没有完整的 link 到 document/file/image,等等,他们将收到 403 禁止访问错误消息。
只需将文件另存为.htaccess
另外,不要将图像保存在数据库中,只需保存文件名,然后将图像上传到上传文件夹,然后就会有类似的东西:
<img src="uploads/<?php echo $row['image_name']; ?>">
这样一来,如果用户可以访问您的数据库(顺便说一句,那是您的错),他们所能访问的只是文件名,而不是实际图像。
你也可以试试@heXer说的。创建一个系统,只有当用户登录时,他们才能查看图像,否则显示错误消息或将他们重定向到另一个页面。
执行以下操作将解决您的问题:
将图像文件存储在隐蔽的地方,例如
public_html
区域中的目录文件夹结构。在此父文件夹中,您可以使用 htaccess 和 simply deny all access to the files 防止热链接。 (存储在 public html 区域内比存储在 html 区域外更安全)。# htaccess full file: Options -Indexes Deny from all
使用PHP文件来引用您要显示的图像;例如:
echo "<img src='uploadsFolder/showImage.php?img=".$row['imghash']."' />";
上面引用的 PHP 文件 - “showImage.php” - 然后可以在数据库中搜索这个唯一的哈希列。一旦找到,PHP 文件就会使用
file_get_contents()
to load the image and then output this image to the<img>
link with the appropriate headers.将散列列添加到现有数据并填充它 (generate random strings). Ensure it is indexed as unique.
结果
图像文件应不与PHP图像显示文件存储在同一文件夹中。该文件夹不仅包含您的 PHP 文件。显然,为了方便起见,您可以更改此文件夹的位置(例如:/imageToucher/showImage.php?img=".$row['imghash']."
等),或者您可以使用 quick universal find and replace 更新 MySQL 中的图像文件路径。
现在每次您想加载任何受保护的文件时;您只需调用 PHP 文件,让它完成检查数据库的散列、获取关联的文件路径、从该路径抓取文件、加载它、解析它然后将其作为输出输出的工作PHP 文件本身。
此方法的好处
- 您的源文件路径永远不会被泄露。
- 您可以通过 PHP 中的
sleep()
语句快速限制(延迟)试图查找不存在文件的人,因此循环使用不同$_GET['img']
值的人速度会很快变慢(您可以使用会话或 IP 跟踪器或类似工具来记录加载图像 URL 的失败尝试次数) - PHP 文件可以处理找到的任何有效图像,因此您可以按缩略图大小显示图像,或根据需要设置其他输出标准。
一个小缺点可能是此文件夹中的数据需要通过网站另一部分的代码进行解析才能显示,因为 .htaccess
将拒绝所有直接访问,这包括网页中的引用,因此访问必须通过 PHP 和数据库来收集有效的 URL。这会使缩略图列表等在繁忙的场景中处理器负担更大且效率更低。