防止用户 URL 输入中的 XSS

Preventing XSS in user URL input

我有一个带有输入字段的应用程序,允许用户提交 URL,它将在页面上显示为 link(在用 React 编写的 SPA 中)。

我希望用户能够提交相对 URL 和绝对 URL。例如(以下所有内容都应该是一个很好的输入):

https://whosebug.com
whosebug.com
http://example.com
localhost:1234
localhost
...

我正在尝试防止 XSS 攻击。因此,当用户在 URL 输入中提交 javascript:alert('hacked') 时,它应该不起作用。

我考虑的方法是简单地在输入前加上 http:// 前缀(如果它不在输入中)。这样最后的结果就是 http://javascript:alert('hacked')

在服务器端,我正在使用 ASP.NET 核心,我有一个看起来像这样的模型:

using System.ComponentModel.DataAnnotations;

namespace MyApp.Models {
    public class LinkModel {
        [Required]
        public string Title { get; set; }

        [Url]
        public string Url { get; set; }
    }
}

注意 Url 属性,当我测试时 - http://javascript:alert('hacked') 它是 "valid"。这让我相信它没问题,而且它不是 XSS 攻击媒介。我也在 Chrome 和 Firefox 中测试过它似乎是 "safe".

是这样吗?我错过了什么吗?在将输入传递给服务器之前将 http:// 添加到足以防止 XSS 攻击的输入。如果我可以澄清,请告诉我。

如果您要接受用户的 URL,则需要注意一些事项。您提到了 javascript: 向量。还有data: urls(例如,data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=会弹出一个警告说"hello"。)在我看来,你需要解析url,并确保 scheme/protocol 在白名单中(例如,httpshttp)。此白名单将取决于您的需要。也许您希望人们能够使用 mailto:slack: link,但您需要了解每种协议可能存在的攻击或滥用类型。仅附加 http 有点奇怪,最终可能会出现漏洞。例如 http://test@http://example.com 可以使用 basic HTTP authentication 将用户名 http 和密码 //test 传递给主机 example.com。我怀疑这是否适用于现代浏览器,但这是可能的。

就其价值而言,http://javascript:alert(1) 永远不应被解释为 javascript。我猜浏览器会将 javascript 解释为主机(比如 whosebug.com 是主机)。但是如果主机在其网络上有一台名为 javascript 的计算机,它将解析为一个错误页面。如果你正确地实现了白名单,你就不需要担心这样的事情了。

接下来,您需要确保您在显示时escaping/encoding和URL是正确的。像这样: <a href="escape(url)">name</a> 您需要确保用户不能将 " 放入 url 并突破 html 属性。考虑类似 system.web.security.antixss.antixssencoder.urlencode.

您还需要注意,用户仍然可以 link 恶意的有效 https 站点。一个例子是看起来像您的网络钓鱼站点,或者可能只是一些带有恶意软件下载的站点。许多网站会创建一个警告弹出窗口,告诉用户他们将离开该网站。这可能是你想做的事情,但这真的取决于。我不确定这些有多大帮助,但如果您担心用户被诱骗离开,则需要考虑一下。

最后,用户可能 link 到您网站上的现有页面并且仍然是恶意的 - 例如,CSRF。您需要小心防止这些类型的页面存在。想象一下有人 link 访问 https://example.com/account/delete,然后一个毫无戒心的用户删除了他们自己的帐户。

编辑:我个人不会在没有该方案的情况下让用户输入 URLs,因为这意味着您必须假设 http。我会在客户端验证它是 URL(包括协议),然后检查它是否在白名单中。