使用用户提供的URL进行服务器端urllib2.urlopen操作时需要考虑安全问题。

4
我希望用户能够通过提供URL从网络上传图像。由于可能存在CORS问题和防止热链接,我认为我无法让客户端获取并上传图像,所以我让服务器来处理它。
最大的问题是用户简单地输入了file:///home/user/secret_image.jpg。该URL被发送到服务器,并被django愉快地获取,成为一个本地服务器端文件,供全世界查看。有没有办法限制对外部资源的请求?如何使这种方法变得安全(至少在某种程度上呢)?
一些其他问题可能是用户提供解析为本地地址的主机名或提供公共URL重定向到本地地址。即使是LAN上的其他设备也是如此,它们通常是不可访问的。
过滤URL文本不是一个选项。我可以检查IP是否被路由到网关,并且目标是否在我的子网之外,然后才允许urllib继续。我可以阻止任何重定向,但这在某些情况下可能是一项有用的功能,因此我可以编写一个重定向处理程序来重新检查IP。现在这开始感觉像是一个补丁工作而不是一个很好的、强壮的处理所有情况的解决方案。
我还做一些基本的事情,比如使用read(max_size)来检查文件是否过大,使用python-magic来检查mimetype并选择一个扩展名,使用django-ratelimit并在调用urlopen()时设置超时。
编辑:相关答案

我不太确定我理解你所关心的内容。如果你想要防止特定类型的 URL,则应在表单或视图中验证输入;无论如何,你都应该始终对用户提供的输入进行验证。 - Daniel Roseman
1
我并不真的相信自己能够针对URL进行黑名单处理。我希望有更通用的解决方案。例如,我假设如果它是公开可用的图像,那么Django获取它应该是可以的。但是对于本地文件、地址,甚至是本地网络中的其他地址和域名等,该怎么办呢? - jozxyqk
1
你想要保护的漏洞是服务器端请求伪造(SSRF) - SilverlightFox
1个回答

1

考虑到这可能涉及大量的网络I/O,我建议将工作移动到“文件下载工作者”,例如使用Celery,但任何其他解决方案,甚至是自制的,都可以用于此部分。

文件系统

下一步是,一旦您将主要的Django部署与其工作者分开,您可以使用不同的非特权OS用户来运行工作者,您可以在chroot或另一个类似的监狱中运行。这应该限制工作者在其文件系统上可以看到什么。

网络接口

至于网络接口,您可以设置防火墙规则,例如我相信在Linux操作系统上,iptables可以为每个用户和每个网络接口设置规则。因此,这应该允许您限制工作者用户在其网络上可以执行的操作。

底线

底线是,我会将任务移动到一个单独的工作进程中,该进程具有非特权和受限制的访问计算机资源的权限,而不是继承主要Django应用程序的权限。唯一授予工作进程的特权将是访问互联网,获取一些文件,将其写回磁盘,仅此而已。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接