Blacklist/whitelist XSS

Blacklist/whitelist for XSS

我需要实现XSS防御,但遇到了麻烦。 我读了这个备忘单 https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html 有很多有价值的信息,但对我来说实施起来相当困难。 我明白,你需要逃避不受信任的数据,我已经在我的应用程序中实现了它,但我还需要实现某种 blacklist/whitelist,对吧?数据中允许什么,不允许什么。 我试图在我的服务器端(即 java)使用此代码,但我需要在前端使用类似的东西。我正在使用核心 javascript 和 jquery

  1. 这是个好方法吗?
  2. 是否有任何库可以帮助我构建 blacklist/whitelist?
  3. 或者如何确保转义数据不包含 javascript: 等?
  4. 我找到了这个用于转义字符的库。 https://github.com/YahooArchive/xss-filters/wiki可以用吗?

        // Avoid anything between script tags
        Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Avoid anything in a src='...' type of expression
        scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\'(.*?)\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
    
        scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\"(.*?)\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Remove any lonesome </script> tag
        scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Remove any lonesome <script ...> tag
        scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Avoid eval(...) expressions
        scriptPattern = Pattern.compile("eval\((.*?)\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Avoid expression(...) expressions
        scriptPattern = Pattern.compile("expression\((.*?)\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Avoid javascript:... expressions
        scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Avoid vbscript:... expressions
        scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
        value = scriptPattern.matcher(value).replaceAll("");
    
        // Avoid onload= expressions
        scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        value = scriptPattern.matcher(value).replaceAll("");
    

您可以添加文本转义来阻止 反射 XSS 攻击,但您应该真正考虑在您的 Web 服务器上实施安全 headers 以阻止 存储 XSS攻击。

查看 CSP Security Header 以获得有关如何实施它的详细说明和文档。如果你使用像 NGINX 这样的东西,它很容易实现。

如果您对这种 XSS 攻击之间的区别有任何疑问,请告诉我。

黑名单实际上不起作用。它们只能涵盖与程序员已经想到的模式相匹配的攻击,但始终会发现新的变体和技术。例如,参见 XSS Filter Evasion Cheat Sheet

像 Chrome 这样的浏览器已经付出了巨大的努力来尝试使用他们的过滤器来检测 XSS,但即便如此,他们现在仍计划将其删除,因为它充满了漏洞并阻止了合法输入 (Google to remove Chrome's built-in XSS protection)

您发现的过滤器特别糟糕。有明显的遗漏,比如它寻找 onload 而不是 onmouseover。它不处理嵌套值,因此 <vbscript:script>alert(1)</scriptvbscript:> 变为 <script>alert(1)</script>。还有很多类型的 XSS 攻击,如果多个参数一起使用,这种过滤器无法检测到。

相反,请关注备忘单上的 OWASP 规则。在这里,有一些白名单的用途,但它们更容易实现,因为它们正在寻找特定的已知值。因此,规则 #7(避免 JavaScript URLs)可以通过在任何 URL 开头查找 'http:' 或 'https:' 来实现输出。规则 #6(清理 HTML 标记)可以使用另一个配置为仅允许特定标签和值的库来实现。

Yahoo 库看起来足够合理,可以转义,但看起来不再维护了。他们出于性能原因转义尽可能少的字符的方法需要比其他一些库更多的方法,您需要更加小心地为每个上下文使用完全正确的方法(例如 inSingleQuotedAttrinDoubleQuotedAttr)。相反,我会使用至少转义 &<>"' 的库来进行 HTML 转义和那么很多这些方法可以合并在一起。

使用 JavaScript,大多数现代模板语言默认会转义值,或者您可以坚持使用基于文本的 DOM 方法,例如 $().attr()$().text() 而不是$().html(),那么就不需要外部转义库了。

这可能对前端有帮助,您也可以在后端使用它。

String.prototype.preventXss = function () {
  const blackList = /['</>']/g;
  return this.replace(blackList, '');
};

let mystring = '<h1>';
console.log(mystring.preventXss());