避免使用XSS并允许一些带有JavaScript的html标签

时间:2013-11-06 22:37:32

标签: javascript jquery xss

我当前的项目遇到了问题: 用户可以使用textarea发送电子邮件。我们允许用户输入他们想要的内容,从而允许用于格式化的HTML。 例如,应允许用户将<b>标记用于粗体文本。

完成电子邮件后,用户应该能够动态查看其电子邮件的预览。

但是有一个小问题,如何在显示预览时避免XSS黑客攻击?

您可以使用underscore.js删除它们,但这不会格式化它们的预览。

所以我暂时禁止所有HTML代码,只允许使用<hr><b>等代码。

您对此解决方案有何看法?它足够安全吗?

5 个答案:

答案 0 :(得分:7)

为了防止应用程序受到XSS攻击,我通常使用以下规则:

  1. 确定应用程序的安全级别。
    有几种工具可以保护您的应用程序,OWASP工具提供了更好的安全性:ESAPIAntySami
    注意:使用Sanitization并不能保证过滤掉所有恶意代码,因此工具的安全性可能更高或更低。

  2. 了解您是否需要在客户端,服务器或双方执行清理。在大多数情况下,它足以在服务器端执行此操作。

  3. 了解是否需要保留html标记(以及需要保留的标记)。如前所述,不允许使用html标签是更安全的解决方案。

  4. 基于此,您可以找到一个正确的决定 1.我个人使用jSoup进行服务器代码清理。至于我,这是非常好的工具。
    通常为了检查输入漏洞,我使用以下向量:

    ';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//\";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
    
    1. 如果您需要在客户端阻止XSS,您可以使用以下工具:
      a)JSSANItazer似乎有点过时了 b)Dust - 由twitter维护;
    2. 这些工具可以轻松地让您清理输入,主要是回答您的问题。

      上面提到的服务器端工具。

      关于第3点。 如果您不需要处理html标记,则可以在服务器端轻松使用ESAPI,在客户端轻松使用ESAPI4JS。据我所知它不适合你。

      当我阅读你的任务时,我知道你正在存储电子邮件消息,因此在你的情况下,它需要在服务器端清理输入(使用工具之一),并按照你的意愿添加或不在客户端添加。您只需要决定是在UI端添加另一个清理还是在服务器上呈现“预览页面”。

答案 1 :(得分:1)

你可以总是切换到使用BB code,使用相同的解析器作为表单进行预览,然后在发送时解析ubb代码服务器端。

如果您想要解析BB代码客户端以进行预览,请参阅this文章,并使用this解析BB代码服务器端,假设您使用PHP发送邮件。

答案 2 :(得分:1)

避免大多数XSS攻击的最佳方法是:

这两者将使您的网站非常健壮

答案 3 :(得分:0)

我认为,由于在电子邮件客户端中使用的标签是一个相对较小(但仍然相当大)的列表,因此您可能希望使用标签白名单,类似于您现在正在执行的操作。删除标签但是你允许的标签是一个相对复杂的重复文本,但我认为这是允许某些标签而不是其他标签的唯一方法。这不是万无一失的,因为删除标签可用于创建新标签,例如在我的输入下面,假设是不允许的,你将它剥离出来:

<<script>script language="javascript">Do something bad</<script>script>

您可能希望使用markdown或一些类似的语法来探索,这些语法可以在服务器端转换为一些有效的HTML。

请参阅http://daringfireball.net/projects/markdown/

这样,他们可以使用一小部分格式标记,你可以在服务器端替换它们。

答案 4 :(得分:-1)

如果你想在服务器端阻止XSS攻击而允许使用某些标签,你可以使用OWASP HTMLSanitizer(OWASP antisamy现在处于非活动状态)并制定你自己的规则。

  • HTML清理工具页面:
    https://www.owasp.org/index.php/OWASP_Java_HTML_Sanitizer_Project
  • 示例规则 - 易趣规则:
    https://github.com/OWASP/java-html-sanitizer/blob/master/src/main/java/org/owasp/html/examples/EbayPolicyExample.java

    https://github.com/OWASP/java-html-sanitizer/blob/master/src/main/java/org/owasp/html/examples/EbayPolicyExample.java
    public static final PolicyFactory POLICY_DEFINITION = new HtmlPolicyBuilder()
          .allowAttributes("id").matching(HTML_ID).globally()
          .allowAttributes("class").matching(HTML_CLASS).globally()
          .allowAttributes("lang").matching(Pattern.compile("[a-zA-Z]{2,20}"))
              .globally()
          .allowAttributes("title").matching(HTML_TITLE).globally()
          .allowStyling()
          .allowAttributes("align").matching(ALIGN).onElements("p")
          .allowAttributes("for").matching(HTML_ID).onElements("label")
          .allowAttributes("color").matching(COLOR_NAME_OR_COLOR_CODE)
              .onElements("font")
          .allowAttributes("face")
              .matching(Pattern.compile("[\\w;, \\-]+"))
              .onElements("font")
          .allowAttributes("size").matching(NUMBER).onElements("font")
          .allowAttributes("href").matching(ONSITE_OR_OFFSITE_URL)
              .onElements("a")
          .allowStandardUrlProtocols()
          .allowAttributes("nohref").onElements("a")
          .allowAttributes("name").matching(NAME).onElements("a")
          .allowAttributes(
              "onfocus", "onblur", "onclick", "onmousedown", "onmouseup")
              .matching(HISTORY_BACK).onElements("a")
          .requireRelNofollowOnLinks()
          .allowAttributes("src").matching(ONSITE_OR_OFFSITE_URL)
              .onElements("img")
          .allowAttributes("name").matching(NAME)
              .onElements("img")
          .allowAttributes("alt").matching(PARAGRAPH)
              .onElements("img")
          .allowAttributes("border", "hspace", "vspace").matching(NUMBER)
              .onElements("img")
          .allowAttributes("border", "cellpadding", "cellspacing")
              .matching(NUMBER).onElements("table")
          .allowAttributes("bgcolor").matching(COLOR_NAME_OR_COLOR_CODE)
              .onElements("table")
          .allowAttributes("background").matching(ONSITE_URL)
              .onElements("table")
          .allowAttributes("align").matching(ALIGN)
              .onElements("table")
          .allowAttributes("noresize").matching(Pattern.compile("(?i)noresize"))
              .onElements("table")
          .allowAttributes("background").matching(ONSITE_URL)
              .onElements("td", "th", "tr")
          .allowAttributes("bgcolor").matching(COLOR_NAME_OR_COLOR_CODE)
              .onElements("td", "th")
          .allowAttributes("abbr").matching(PARAGRAPH)
              .onElements("td", "th")
          .allowAttributes("axis", "headers").matching(NAME)
              .onElements("td", "th")
          .allowAttributes("scope")
              .matching(Pattern.compile("(?i)(?:row|col)(?:group)?"))
              .onElements("td", "th")
          .allowAttributes("nowrap")
              .onElements("td", "th")
          .allowAttributes("height", "width").matching(NUMBER_OR_PERCENT)
              .onElements("table", "td", "th", "tr", "img")
          .allowAttributes("align").matching(ALIGN)
              .onElements("thead", "tbody", "tfoot", "img",
                               "td", "th", "tr", "colgroup", "col")
          .allowAttributes("valign").matching(VALIGN)
              .onElements("thead", "tbody", "tfoot",
                              "td", "th", "tr", "colgroup", "col")
          .allowAttributes("charoff").matching(NUMBER_OR_PERCENT)
              .onElements("td", "th", "tr", "colgroup", "col",
                              "thead", "tbody", "tfoot")
          .allowAttributes("char").matching(ONE_CHAR)
              .onElements("td", "th", "tr", "colgroup", "col",
                               "thead", "tbody", "tfoot")
          .allowAttributes("colspan", "rowspan").matching(NUMBER)
              .onElements("td", "th")
          .allowAttributes("span", "width").matching(NUMBER_OR_PERCENT)
              .onElements("colgroup", "col")
          .allowElements(
              "a", "label", "noscript", "h1", "h2", "h3", "h4", "h5", "h6",
              "p", "i", "b", "u", "strong", "em", "small", "big", "pre", "code",
              "cite", "samp", "sub", "sup", "strike", "center", "blockquote",
              "hr", "br", "col", "font", "map", "span", "div", "img",
              "ul", "ol", "li", "dd", "dt", "dl", "tbody", "thead", "tfoot",
              "table", "td", "th", "tr", "colgroup", "fieldset", "legend")
          .toFactory();