【问题标题】:Preventing XSS in user URL input防止用户 URL 输入中的 XSS
【发布时间】:2020-02-04 19:04:19
【问题描述】:

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

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

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

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

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

在服务器端,我使用的是 ASP.NET Core,并且我有一个看起来像这样的模型:

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') 它是“有效的”。这让我相信它没问题,它不是 XSS 攻击向量。我还在 Chrome 和 Firefox 中进行了测试,它似乎是“安全的”。

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

【问题讨论】:

  • 你读过this section for recommendations?吗,你也可以在把文本/url放入href之前对其进行清理,例如:使用HtmlSanitizer
  • 我实际上是在将数据从 ASP.NET 控制器以 JSON 格式传递到反应前端。所以我想我的问题更笼统。 (我已经更新了我的问题,如果它可以澄清一点)。

标签: c# asp.net security asp.net-core xss


【解决方案1】:

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

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

接下来,您需要确保在显示 URL 时正确转义/编码 URL。像这样:<a href="escape(url)">name</a> 你需要确保用户不能将" 放在 url 中并打破 html 属性。考虑类似system.web.security.antixss.antixssencoder.urlencode

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

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

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

【讨论】:

  • 感谢您的详细回答,非常感谢。在您的第一个示例中,data: 是一个攻击向量。 http:// 前缀不会像 javascript: 一样使其无效吗?你最后一个建议的问题是,如果用户要输入网址(而不是复制粘贴),我想让他们更容易一些,大多数人只会去google.com
  • 说我接受你的建议并让用户输入协议。什么是验证网址的好方法。我见过一些疯狂的 RegEx 试图这样做。有什么建议么?链接?阅读材料?
  • 是的。 http://data 就像链接到用户网络上名为 data 的计算机。这样做有点奇怪,IMO。我知道你的意思是用户输入google.com 比输入https://google.com 更容易,但假设http 也可能导致错误。如果该站点没有在端口 80 上侦听,那么它就会超时。大多数网站都会有一个 http->https 重定向,但你也提到了一些 localhost 网站。
  • 为了验证 URL 客户端,您不需要任何花哨的东西(我不鼓励它)。 <input type="url" pattern="https?://.+" required /> 这只会保证 http 或 https。在服务器端进行验证仍然是绝对关键的,因为攻击者可以绕过任何客户端验证。在服务器端,您希望依赖内置的 URL 解析器,而不是正则表达式。
  • 是的,当然,我也会进行服务器端验证(已经由 asp.net 及其Url 验证属性完成)。再次感谢您的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
  • 2015-09-17
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
相关资源
最近更新 更多