如何使用用户给定的 URL 安全地嵌入 <img> 标记?

信息安全 Web应用程序 网页浏览器 xss 铬合金 html
2021-08-15 05:43:39

如果我假设希望允许用户使用来自任意 URL 的头像,如下所示:

<img class="avatar" src="{user input}" />

我能想到的问题有很多:

  • data uris可能创建一个独立的 PDF 文件;这实际上会在<img />标签内工作吗?
  • javascript:适用于<a />元素的符号
  • 服务器可能会以未经授权的 401 响应并请求基本身份验证,用户会很想尝试自己的用户/密码组合
  • 服务器可能会返回一个巨大的图像

而且可能更多。

有没有办法在不实际下载和提供该图像的情况下使其安全?

1个回答

避免对您的网站的攻击

您需要验证收到的字符串是否有效。请记住这个原则:您必须将可接受的字符串列入白名单,而不是将不可接受的字符串列入黑名单。

  1. 确保字符串是语法正确且转义的 URL转义整个 URL 可以避免它包含 " 或 > ,这可能会破坏您网站的语法。
  2. 确保 URL 是绝对的,以帮助避免目录遍历攻击您还需要弄清楚您的 Web 服务器如何处理可从您的/var/www文件夹中访问的符号链接,以及您的服务器如何使用对父目录的引用来解析绝对 URL,例如www.server.com/../../../etc/passwd.
  3. 确保 URL 使用您了解其含义的已知、受支持的协议:httphttps. ¹

保护用户隐私

先验地检查所指向的文件实际上是没有意义的,因为提供链接的用户可以在您不知情的情况下随时更改它。如果该代码在浏览器的呈现例程中触发错误,那么呈现您网站的(沙盒)浏览器进程将受到威胁。

您应该知道,图像可用于收集您自己用户的 IP 地址。攻击者只需要等待并收集哪些 IP 地址查询他们用于您网站的图像。

401 攻击现在应该已修复,但某些浏览器可能仍无法正确处理它。已在此StackExchange 线程上进行了讨论根据这个 Chrome bug tracker thread,当图像触发 401 错误时,Chrome 不再显示身份验证提示。

这两种威胁有一个通用的解决方案:下载和缓存图像如果您能负担得起,您将更有把握确保用户安全。我知道这不是你想要的,但这是你最好的行动方案。

避免对您的服务器的攻击!

由于您现在正在缓存图像,因此您需要再次将其列入白名单。

  1. 确保图像对应于您支持的文件格式之一(例如 PNG/SVG/JPG/GIF)
  2. 确保图像在语法上正确
  3. 通过提取与显示图像相关的任何信息并转储您不认识或不需要的任何信息来重构图像 - 例如,据称 SVG 文件可以嵌入 JavaScript,您可能不希望这样做,因为它会在您的域中由浏览器。²
  4. 对图像的分辨率和文件大小施加合理的限制

¹ 有人指出,攻击者可以执行诸如file:///some/user/secret/on/their/local/machine. 如果您没有检索文件而只是保留了 URL,这可能会导致文件被呈现您的站点的呈现进程加载。与成功利用渲染中的错误的图像的第二个URL 相结合,攻击者可以检索此文件的内容。

² 请注意,SVG 文件特别危险,目前没有可用的工具来过滤它们。