Preventing XSS in user URL input
我有一个带有输入字段的应用程序,它允许用户提交一个 URL,该 URL 将作为链接显示在页面上(在用 React 编写的 SPA 中)。
我希望用户能够提交相对网址以及绝对网址。例如(以下所有内容都应该是一个很好的输入):
1 2 3 4 5 6
| https://stackoverflow.com
stackoverflow.com
http://example.com
localhost:1234
localhost
... |
我正在努力防止 XSS 攻击。这样当用户在 URL 输入中提交 javascript:alert('hacked') 时,它应该不起作用。
我想这样做的方法是简单地用 http:// 前缀输入(如果它已经不在输入中)。所以最终结果是 http://javascript:alert('hacked')
在服务器端,我使用的是 ASP.NET Core,我有一个看起来像这样的模型:
1 2 3 4 5 6 7 8 9 10 11
| 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 攻击。如果我能澄清,请告诉我。
- 您是否已阅读本节以获取建议?,您还可以在将文本/网址放入 href 之前对其进行消毒,例如:使用 HtmlSanitizer。
-
我实际上是将数据从 JSON 中的 ASP.NET 控制器传递到反应前端。所以我想我的问题更笼统。 (我已经更新了我的问题是否可以澄清一些事情)。
如果您接受来自用户的 URL,则需要注意一些事项。您提到了 javascript: 向量。还有 data: url(例如,data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4= 会弹出一个提示"你好"。)在我看来,你需要解析 url,并确保方案/协议是白色的列表(例如,https 和 http)。此白名单将取决于您的需要。也许您希望人们能够使用 mailto: 或 slack: 链接,但您需要了解每种协议可能存在的攻击或滥用类型。只是附加 http 有点奇怪,最终可能会有一个漏洞。例如,http://test@http://example.com 可以使用基本的 HTTP 身份验证将用户名 http 和密码 //test 传递给主机 example.com。我怀疑这在现代浏览器中是否有效,但这是可能的。
就其价值而言,http://javascript:alert(1) 永远不应被解释为 javascript。我猜浏览器将 javascript 解释为主机(如 stackoverflow.com 是主机)。但是,如果主机在其网络上有一台名为 javascript 的计算机,它将解析为错误页面。如果你正确地实现了白名单,你就不需要担心这样的事情。
接下来,您需要确保在显示 URL 时正确转义/编码 URL。像这样: name 您需要确保用户不能将 " 放入 url 并突破 html 属性。考虑像 system.web.security.antixss.antixssencoder.urlencode.
这样的东西
您还需要注意,用户仍然可以链接恶意的有效 https 站点。一个例子是一个看起来像你的网络钓鱼网站,或者可能只是一些下载恶意软件的网站。许多站点会创建一个警告弹出窗口,告诉用户他们将离开站点。这可能是您想做的事情,但这确实取决于。我不确定这些有多大帮助,但是如果您担心用户被诱骗离开,则需要考虑一下。
最后,用户可以链接到您网站上的现有页面,但仍然是恶意的 - 例如,CSRF。您需要小心防止这些类型的页面存在。想象一下有人链接到 https://example.com/account/delete,然后一个毫无戒心的用户删除了他们自己的帐户。
edit:我个人不会让用户在没有方案的情况下输入 URL,因为这意味着您必须假设 http。我会在客户端验证它是一个 URL(包括协议),然后检查它是否在白名单中。
- 谢谢详细解答,不胜感激。在您的第一个示例中, data: 是一个攻击向量。 http:// 前缀不会像 javascript: 一样使其无效吗?你最后一个建议的问题是,如果用户要输入 url(而不是复制粘贴),我想让他们更容易一些,大多数人只会去 google.com。
-
假设我接受您的建议并让用户输入协议。什么是验证 url 的好方法。我见过一些疯狂的 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 验证属性完成)。再次感谢您的回答。