通过用户input的URL来处理安全性和避免XSS的最佳方式

我们有一个高安全性的应用程序,我们希望允许用户input其他用户将会看到的URL。

这引入了XSS黑客的高风险 – 一个用户可能会inputJavaScript,另一个用户最终执行。 由于我们持有敏感数据,所以这绝对不会发生。

处理这个问题的最佳做法是什么? 任何安全白名单或逃生模式单独足够好?

有关处理redirect的任何build议(例如,在链接之前的警告页面上的“此链接超出我们的网站”消息)

有没有支持用户input链接的论据?


澄清:

基本上我们的用户想要input:

stackoverflow.com

并将其输出给另一个用户:

<a href="http://stackoverflow.com">stackoverflow.com</a> 

我真正担心的是他们在XSS黑客中使用这个。 即他们input:

警报( '砍死!');

所以其他用户得到这个链接:

 <a href="alert('hacked!');">stackoverflow.com</a> 

我的例子只是解释风险 – 我很清楚,JavaScript和URL是不同的东西,但通过让他们input后者,他们可能能够执行前者。

你会惊讶有多less网站可以打破这个伎俩 – HTML是更糟糕的。 如果他们知道处理链接,他们也知道清理<iframe><img>和聪明的CSS引用?

我正在一个高度安全的环境中工作 – 单一的XSS攻击可能会给我们带来非常高的损失。 我很高兴能够制作一个正则expression式(或者使用迄今为止的一个很​​好的build议),这样可以排除我所能想到的所有事情,但是这样做还可以吗?

如果您认为url不能包含代码,请再考虑一下!

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

阅读,并哭泣。

以下是我们如何在堆栈溢出做到这一点:

 /// <summary> /// returns "safe" URL, stripping anything outside normal charsets for URL /// </summary> public static string SanitizeUrl(string url) { return Regex.Replace(url, @"[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]", ""); } 

渲染链接“安全”的过程应该经过三到四个步骤:

  • 对所给的string进行Unescape /重新编码(RSnake在http://ha.ckers.org/xss.html中logging了许多使用转义和UTF编码的技巧)。;
  • 清理链接:正则expression式是一个好的开始 – 确保截断string或​​抛出它,如果它包含一个“(或任何你用来closures你的输出中的属性);如果你只做链接作为参考到其他信息,你也可以在这个过程结束时强制协议 – 如果第一个冒号前的部分不是“http”或“https”,那么在起始处附加“http://”,这样可以创build可用的不完整的input作为用户的链接将input到浏览器,并给你最后一枪,在任何人试图潜入恶作剧。
  • 检查结果是一个格式正确的URL(protocol://host.domain [:port] [/ path] [/ [file]] [?queryField = queryValue] [#anchor])。
  • 可能检查结果对站点黑名单或尝试通过某种恶意软件检查器获取它。

如果安全是重中之重,我希望用户能在这个过程中原谅一些偏执狂,即使它最终会抛弃一些安全的链接。

使用一个库,例如OWASP-ESAPI API:

阅读以下:

例如:

 $url = "http://stackoverflow.com"; // eg, $_GET["user-homepage"]; $esapi = new ESAPI( "/etc/php5/esapi/ESAPI.xml" ); // Modified copy of ESAPI.xml $sanitizer = ESAPI::getSanitizer(); $sanitized_url = $sanitizer->getSanitizedURL( "user-homepage", $url ); 

另一个例子是使用一个内置函数。 PHP的filter_var函数就是一个例子:

 $url = "http://stackoverflow.com"; // eg, $_GET["user-homepage"]; $sanitized_url = filter_var($url, FILTER_SANITIZE_URL); 

使用filter_var 可以调用javascript,并且会过滤出既不是http也不是https 。 使用OWASP ESAPI Sanitizer可能是最好的select。

又一个例子是WordPress的代码:

此外,由于无法知道URL链接的位置(例如,它可能是一个有效的URL,但是URL的内容可能会是恶作剧),Google可以调用一个安全的浏览 API:

滚动自己的卫生正则expression式是有问题的几个原因:

  • 除非你是Jon Skeet,否则代码将会出错。
  • 现有的API有许多小时的审查和testing。
  • 现有的URLvalidationAPI考虑国际化。
  • 现有的API将随着新兴的标准而保持最新。

其他要考虑的问题:

  • 你允许哪些scheme(是file:///telnet://可以接受)?
  • 你想要在URL的内容上添加什么限制(可接受的恶意URLs)?

当你输出这些链接的时候,只需要HTM编码链接。 确保你不允许javascript:链接。 (最好有一个可接受的协议白名单,例如http,https和mailto。)

您不指定您的应用程序的语言,然后我会推定ASP.NET,为此,您可以使用Microsoft Anti-Cross站点脚本库

这是非常容易使用,所有你需要的是包括,这是它:)

在讨论这个话题的时候,为什么不给一个关于安全Web应用程序devise指南的文章

如果有任何其他的语言….如果有一个ASP.NET的库,必须可用于其他types的语言(PHP,Python,ROR等)

如何不显示他们作为一个链接? 只要使用文字。

结合警告自行承担风险可能就足够了。

另外 – 另请参见我应该消毒托pipeCMS的HTML标记吗? 讨论消毒用户input

您可以使用hex代码来转换整个URL并将其发送到您的服务器。 这样客户就不会第一眼就看不懂内容。 阅读内容后,您可以解码内容URL =? 并发送给浏览器。

允许一个URL并允许JavaScript是两件不同的事情。