通过用户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:
- PHP – http://code.google.com/p/owasp-esapi-php/
- Java – http://code.google.com/p/owasp-esapi-java/
- .NET – http://code.google.com/p/owasp-esapi-dotnet/
- Python – http://code.google.com/p/owasp-esapi-python/
阅读以下:
- https://www.golemtechnologies.com/articles/prevent-xss#how-to-prevent-cross-site-scripting
- https://www.owasp.org/
- http://www.secbytes.com/blog/?p=253
例如:
$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是两件不同的事情。