避免 XSS 并允许一些带有 JavaScript 的 html 标签
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19824338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Avoid XSS and allow some html tags with JavaScript
提问by VladJS
I've got a problem in my current project:
Users can send an email using a textarea. We allow the user to put in whatever they want, and thus some HTML for formatting.
For example, the user should be allowed to use the <b>
tag for bold text.
我在当前项目中遇到了一个问题:用户可以使用 textarea 发送电子邮件。我们允许用户输入他们想要的任何内容,因此一些 HTML 用于格式化。例如,应该允许用户将<b>
标记用于粗体文本。
After completing their email, the user should be able to view a preview of their email dynamically.
完成电子邮件后,用户应该能够动态查看电子邮件的预览。
There is a slight problem though, how can I avoid XSS hacks when the preview is being displayed?
但是有一个小问题,在显示预览时如何避免 XSS 黑客攻击?
You can ofcourse strip them using underscore.js
, but that wouldn't format their preview.
您当然可以使用 删除它们underscore.js
,但这不会格式化它们的预览。
So I have forbidden all HTML tags for now, and only allowed tags like <hr>
, <b>
, etc.
因此,我已禁止所有HTML标签,现在,只允许标签,如<hr>
,<b>
等
What do you think about this solution? Is it secure enough?
你怎么看这个解决方案?是否足够安全?
回答by user1459144
In order to prevent Application from XSS attacks I usually use following rules:
为了防止应用程序受到 XSS 攻击,我通常使用以下规则:
Determine the level of security for your application.
There are several tools that can protect your application as for me better security is provided by OWASPtools: ESAPIor AntySami.
Note:Using Sanitization does not guarantee filtering of all malicious code, so tools can be more or less secure.Understand whether you need to perform sanitization on client, server or both sides. In most cases it's enough to do this on server side.
Understand whether you need to preserve html tags (and what tags you need to preserve) or not. As it was stated previously not allowing html tags is more secure solution.
确定应用程序的安全级别。
有几种工具可以保护您的应用程序,因为OWASP工具提供了更好的安全性:ESAPI或AntySami。
注意:使用 Sanitization 并不能保证过滤所有恶意代码,因此工具或多或少是安全的。了解您是否需要在客户端、服务器或双方上执行清理。在大多数情况下,在服务器端执行此操作就足够了。
了解是否需要保留 html 标签(以及需要保留哪些标签)。如前所述,不允许使用 html 标签是更安全的解决方案。
Based on this you can find a proper decision.
1. Personally for server code sanitization I used jSoup. As for me it's pretty good tool to do this.
Usually In order to check input vulnerability I am using following vector:
基于此,您可以找到正确的决定。
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>
- In case you need prevent XSS on client side you can use following tools:
a) JSSANItazerseems a bit outdated
b) Dust- maintained by twitter;
- 如果您需要在客户端防止 XSS,您可以使用以下工具:
a) JSSANItazer似乎有点过时
b) Dust- 由 twitter 维护;
These tools easily can allow you to sanitize your input and mainly is answer for your question.
这些工具可以轻松地让您清理您的输入,主要是回答您的问题。
Server side tools mentioned above.
上面提到的服务器端工具。
Regarding 3rd point. In case you don't need to handle html tags you can easily use ESAPI on server side and ESAPI4JSon client side. As I understand it doesn't work for you.
关于第三点。如果您不需要处理 html 标签,您可以轻松地在服务器端使用 ESAPI,在客户端使用ESAPI4JS。据我了解,它对您不起作用。
When I read your task I understood that you are storing email message therefore In your case it's required to sanitize input on server side (using one of tools) and it's as per you to add it or not on client side. You need only decide whether add another sanitization on UI side or render your "preview page" on server.
当我阅读您的任务时,我了解到您正在存储电子邮件消息,因此在您的情况下,需要清理服务器端的输入(使用一种工具),并且根据您是否在客户端添加或不添加它。您只需要决定是否在 UI 端添加另一个清理或在服务器上呈现您的“预览页面”。
回答by Thew
You can ofcourse allways switch to using BB code, use the same parser for the preview as the form, and then parse the ubb code server side when sending.
你当然可以一直切换到使用BB码,使用和表单一样的解析器进行预览,然后在发送时解析ubb码服务器端。
See thisarticle if you like to parse the BB code client side for the preview and thisfor parsing the BB code server-side, assuming you send mails using PHP.
回答by fmsf
Best way to avoid most of the XSS attacks is:
避免大多数 XSS 攻击的最佳方法是:
By sanitizing your data so text is properly escaped before it hits the html (you can build exceptions for your
<b>
and<hr>
and othersUsing Content Security Policy to disable all inline scripting (also avoids man in the middle attacks): http://www.html5rocks.com/en/tutorials/security/content-security-policy/
通过消毒数据,以便文本正确逃脱它击中的HTML(你可以建立例外您之前
<b>
并<hr>
和其他人使用内容安全策略禁用所有内联脚本(也避免中间人攻击):http: //www.html5rocks.com/en/tutorials/security/content-security-policy/
These two together will make your site pretty robust
这两个一起将使您的网站非常强大
回答by Jazzuzz
I think since the tags that work in email clients is a relatively small (but still sizeable) list, you might want to use a whitelist of tags, similar to what you're doing right now. It would be a relatively complex regext to strip out tags but the ones you allow, but I think that's the only way you can allow some tags and not others. This is not foolproof though because the deletion of tags can be used to create new tags e.g in my input below, assume is disallowed and you strip it out:
我认为由于在电子邮件客户端中工作的标签是一个相对较小(但仍然相当大)的列表,您可能想要使用一个标签白名单,类似于您现在正在做的事情。去除标签但您允许的标签将是一个相对复杂的正则表达式,但我认为这是您允许某些标签而不是其他标签的唯一方法。但这并不是万无一失的,因为删除标签可用于创建新标签,例如在我下面的输入中,假设是不允许的,然后将其删除:
<<script>script language="javascript">Do something bad</<script>script>
You might want to explore using markdown or some similar syntax that you could convert on the server-side into some valid HTML.
您可能想要探索使用 Markdown 或一些类似的语法,您可以在服务器端将其转换为一些有效的 HTML。
See http://daringfireball.net/projects/markdown/
见http://daringfireball.net/projects/markdown/
That way, they can use a small subset of formatting markdowns and you can substitute them on the server side.
这样,他们可以使用一小部分格式化降价,您可以在服务器端替换它们。
回答by GunHee Lee
If you want to prevent XSS attack on the server side with allowing some tags, you can use OWASP HTMLSanitizer(OWASP antisamy is now inactive) and also make your own rules.
如果您想通过允许某些标签来防止服务器端的 XSS 攻击,您可以使用 OWASP HTMLSanitizer(OWASP antisamy 现在处于非活动状态)并制定您自己的规则。
- HTML sanitizer project page:
https://www.owasp.org/index.php/OWASP_Java_HTML_Sanitizer_Project Example rule - Ebay rule:
https://github.com/OWASP/java-html-sanitizer/blob/master/src/main/java/org/owasp/html/examples/EbayPolicyExample.javahttps://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();
- HTML sanitizer 项目页面:https:
//www.owasp.org/index.php/OWASP_Java_HTML_Sanitizer_Project 示例规则 - Ebay 规则:https:
//github.com/OWASP/java-html-sanitizer/blob/master/src/main/java/org/owasp/html/examples/EbayPolicyExample.javahttps://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();