我有一个简单的上传/检索脚本来从我的数据库中检索图像。当我上传文件时,脚本将它们存储在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 :用户还可以查看我的&#39;的全部内容。 'uploadsFolder/'
内容如果只是他在他/这里的浏览器中键入URL: " localhost/uploadimages/uploads/ "
!!!见附件!
答案 0 :(得分:1)
“此外:用户还可以查看我的全部内容” 'uploadsFolder /'内容如果只有他输入他/这里的浏览器了 网址:“localhost / uploadimages / uploads /”!!!见附件!“
如果您不希望发生这种情况,那么您应该在您的网站上创建.htaccess文件,并在其中包含以下内容:
RewriteEngine on
<ifModule mod_rewrite.c>
Options -Indexes
</IfModule>
这限制了对您网站上任何文件夹的访问,而没有指向文档/文件/图像等的完整链接,他们将收到403 Forbidden错误消息。
只需将文件另存为.htaccess
此外,不是将图像保存在数据库中,只需保存文件名,然后将图像上传到uploads文件夹,然后输入如下内容:
<img src="uploads/<?php echo $row['image_name']; ?>">
如果用户可以访问您的数据库(那将是您的错误),他们可以访问的只是文件名而不是实际图像。
你也可以试试@heXer说的话。创建一个系统,只有当用户登录时,他们才会查看图像,否则会显示错误消息或将其重定向到另一个页面。
答案 1 :(得分:1)
执行以下操作将解决您的问题:
将图像文件存储在某处不明确的位置,例如public_html
区域中的目录文件夹结构。在此父文件夹中,您可以阻止与htaccess和simply deny all access to the files的热链接。 (它更安全地存储在公共html区域内而不是外部)。
# htaccess full file:
Options -Indexes
Deny from all
使用PHP文件引用要显示的图像;如:
echo "<img src='uploadsFolder/showImage.php?img=".$row['imghash']."' />";
上面引用的PHP文件 - &#34; showImage.php &#34; - 然后可以在数据库中搜索此唯一哈希列。找到之后,PHP文件然后使用file_get_contents()
加载图像,然后output this image to the <img>
link with the appropriate headers。
将哈希列添加到现有数据并填充(generate random strings)。确保它是indexed as unique。
图像文件应不存储在与PHP图像显示文件相同的文件夹中。该文件夹不仅包含您的PHP文件。显然,您可以更改此文件夹的位置(例如:/imageToucher/showImage.php?img=".$row['imghash']."
等),或者您可以使用quick universal find and replace更新MySQL中的图像文件路径。
现在每次要加载任何受保护的文件;你只需调用PHP文件,让它完成检查数据库的哈希,获取相关的文件路径,从该路径获取文件,加载它,解析它然后输出它作为PHP文件的输出的工作本身。
sleep()
语句快速限制(延迟)尝试查找不存在的文件的人,以便循环显示不同$_GET['img']
值的人很快就会变慢(您可以使用会话或IP跟踪器或类似工具来记录加载图像URL失败的尝试次数)一个小缺点可能是这个文件夹中的数据需要通过网站的另一部分中的代码进行解析,因为.htaccess
将拒绝所有直接访问,这包括网页中的引用,因此访问必须通过PHP和数据库来收集有效的URL。这可以使缩略图列表等在繁忙的场景中更加重要且效率更低。
答案 2 :(得分:0)
由于您想要显示它们,您需要将它们公开。但是,您可以使用散列(id + timestamp的md5)将它们存储在DB中。这样,名称无法预测。 基本上唯一的方法就是让它变得不可预测。您可以将它们保存为md5(id),但如果有人了解算法,这仍然会使它们有点可预测。
答案 3 :(得分:0)
如果用户可以进行目录列表,您显然已经丢失了。
通常,依靠秘密名称和/或链接而不是实现访问控制是不好的做法。这些秘密往往以各种方式泄漏。例如,拥有look at what happened to DropBox。
当人们尝试这样的事情时,安全性经常失败的另一种方式是使用可预测的随机性而不是加密随机性来获取秘密。 PHP Mersenne Twister随机数生成器是可预测的:知道一些输出(即来自用户被允许知道的图像)将允许用户导出未来输出(未来图像链接)和之前(已经存在的图像链接) 。 PHP's lcg_value也是如此。
底线:无法替代正确的访问控制。否则,您违反了complete mediation security principle,这使您容易受到direct object reference vulnerabilities的攻击。</ p>