处理安全性的最佳方法,并避免使用用户输入的URL进行XSS

Kei*_*ith 54 security xss url html-sanitizing

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

这引入了XSS黑客的高风险 - 用户可能会输入另一个用户最终执行的javascript.由于我们持有敏感数据,因此必须永远不会发生这种情况.

处理这个问题的最佳做法是什么?单独的安全白名单或转义模式是否足够好?

有关处理重定向的任何建议(例如,在关注链接之前,警告页面上的"此链接在我们的网站之外"消息)

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


澄清:

基本上我们的用户想要输入:

stackoverflow.com

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

<a href="http://stackoverflow.com">stackoverflow.com</a>
Run Code Online (Sandbox Code Playgroud)

我真正担心的是他们在XSS黑客中使用它.即他们输入:

警报( '砍死!');

所以其他用户获得此链接:

<a href="alert('hacked!');">stackoverflow.com</a>
Run Code Online (Sandbox Code Playgroud)

我的例子只是解释风险 - 我很清楚javascript和URL是不同的东西,但通过让他们输入后者,他们可能能够执行前者.

你会惊讶于你可以用这个技巧打破多少网站 - HTML更糟糕.如果他们知道处理环节上做到他们也知道消毒<iframe>,<img>并巧妙的CSS参考?

我在高安全性环境中工作 - 单个XSS黑客可能会给我们造成很大的损失.我很高兴我可以制作一个正则表达式(或使用迄今为止的一个很​​好的建议),可以排除我能想到的一切,但这还够吗?

Jef*_*ood 55

如果您认为URL不能包含代码,请再想一想!

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

读了那个,然后哭了.

以下是我们如何在Stack Overflow上执行此操作:

/// <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+&@#/%?=~_|!:,.;\(\)]", "");
}
Run Code Online (Sandbox Code Playgroud)

  • 五年后,我看到没有回复评论,这些评论提供了这个答案如何不安全的例子.然而,这是关于这个话题的最高投票问题(我能找到)的最高投票答案!鉴于堆栈溢出通常是多么棒,我很惊讶我仍然不确定如何安全地实现这种相对常见的场景. (51认同)
  • 这还不够.除非我遗漏了某些内容,否则此字符串将通过过滤器:javascript:alert&#x28;&#x27; hacked&#x27;&#x29; (7认同)
  • 即使这样也可以通过:javascript:while(true)alert('Hacked!'); 我在这里测试了几个地方,看起来SanatizeUrl只是解决方案的一部分. (4认同)
  • 如何在js中做到这一点 (2认同)

Bel*_*ell 14

渲染链接"安全"的过程应该经历三个或四个步骤:

  • Unescape /重新编码你已经给出的字符串(RSnake已经记录了许多技巧) http://ha.ckers.org/xss.html使用转义和UTF编码).
  • 清理链接:正则表达式是一个良好的开端 - 确保截断字符串或​​将其丢弃,如果它包含"(或用于关闭输出中的属性的任何内容);如果您仅将链接作为引用对于其他信息,您也可以在此过程结束时强制执行协议 - 如果第一个冒号之前的部分不是"http"或"https",则在开头附加"http://".这样您就可以创建可用的来自不完整输入的链接,因为用户会输入到浏览器中,并为您提供最后一次尝试绊倒某人试图偷偷摸摸的恶作剧.
  • 检查结果是否格式​​正确(protocol://host.domain [:port] [/ path] [/ [file]] [?queryField = queryValue] [#anchor]).
  • 可能会针对网站黑名单检查结果,或尝试通过某种恶意软件检查程序获取结果.

如果安全是一个优先事项,我希望用户在这个过程中会原谅一点偏执,即使它最终会丢掉一些安全链接.


Dav*_*vis 10

使用库,例如​​OWASP-ESAPI API:

阅读以下:

例如:

$url = "http://stackoverflow.com"; // e.g., $_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 );
Run Code Online (Sandbox Code Playgroud)

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

$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
Run Code Online (Sandbox Code Playgroud)

使用filter_var 允许 javascript调用,并筛选出既不是http也不是的方案https.使用OWASP ESAPI Sanitizer可能是最好的选择.

另一个例子是来自WordPress的代码:

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

滚动自己的正则表达式进行卫生设置是有问题的,原因如下:

  • 除非你是Jon Skeet,否则代码会有错误.
  • 现有的API有许多小时的审查和测试.
  • 现有的URL验证API考虑国际化.
  • 现有的API将与新兴标准保持同步.

其他需要考虑的问题:

  • 你允许什么方案(是file:///telnet://可以接受的)?
  • 您希望对URL的内容施加什么限制(可接受的恶意软件URL)?

  • "这是唯一一个没有被指出不安全的实际代码的答案.恕我直言,最好的答案." 不,不是.`filter_var($ url,FILTER_SANITIZE_URL);`允许例如`javascript:alert();` (2认同)