通过Rails3 xss保护防止语言环境文件中的HTML字符实体受到攻击

时间:2010-08-13 13:58:28

标签: html ruby-on-rails internationalization ruby-on-rails-3 xss

我们正在构建一个应用程序,我们首先使用Rails 3,我们必须从一开始就构建I18n。作为完美主义者,我们希望在我们的观点中使用真正的排版:破折号,卷曲的引号,省略号等。

这意味着在我们的locales / xx.yml文件中我们有两个选择:

  1. 内联使用真正的UTF-8字符。 应该工作,但很难打字,而且 因为金额的原因让我感到害怕 仍然顽皮的软件 事情要unicode。
  2. 使用HTML 字符实体(’ &安培;#8212;等等)。更容易打字, 并且可能更兼容 行为不端的软件。
  3. 我宁愿选择第二个选项,但是Rails 3中的自动转义会使这个问题变得有问题,因为YAML中的&符号会自动转换为字符实体,导致'可见'& 8217; s in浏览器。

    显然,这可以通过在字符串上使用raw来解决,例如:

    raw t('views.signup.organisation_details')
    

    但是,每当我们raw出现问题时,我们都不满意全球t的路线,因为它让我们容易犯错并产生XSS漏洞。

    我们可以有选择地raw我们知道包含字符实体的字符串,但这很难扩展,只是感觉不对 - 此外,包含一种语言的实体的字符串可能不在另一种语言中。

    有关巧妙的rails-y方式的任何建议吗?或者我们注定要废话排版,xss漏洞,浪费时间还是浪费时间?

5 个答案:

答案 0 :(得分:32)

此问题有ticket in lighthouse,解决方案是将_html附加到locales/xx.yml文件中的i18n密钥,并使用t别名 1 表示html_safe字符串。例如:

en:
  hello: "This is a string with an accent: ó"

变为:

en:
  hello_html: "This is a string with an accent: ó"

它会创建以下输出:

  

这是一个带重音的字符串:ó

这样可以防止您必须编写raw t('views.signup.organisation_details')并导致更清晰的输出:t('views.signup.organisation_details_html')。虽然为raw交换_html似乎不是最好的交易,但它确实清楚地表明您正在输出假定为html_safe字符串的内容。

<小时/> 1 我已经测试了灯塔票中建议的代码。我发现你必须专门使用t别名。如果您使用I18n.tI18n.translate,则翻译不会将_html视为html_safe:

I18n.t('hello_html') 
I18n.translate('hello_html') 
# Produces => "This is a string with an accent: &oacute;"

t('hello_html')      
# Produces => "This is a string with an accent: ó"

我认为这不是RoR TranslationHelper documentation的预期行为。

答案 1 :(得分:8)

好。我昨天因为i18n角度给这个问题添加了书签,但没有回答,因为我是一个从不使用过Rails的Python人。我仍然不会回答这个问题,但考虑到你没有被有帮助的Railsians所淹没,他们可以指出你能够绕过Rails的内脏,这仍然是我的观点。

首先,我认为从一开始就考虑问题是伟大的。这非常罕见。其次,我完全同意使用原始字符串或选择性地使用实体选择字符串来对声音进行特殊处理,就像一个脆弱,丑陋,容易出错的黑客。

现在如果我正确理解Rails(我读this i18n guide),YAML文件包含每种语言的本地化字符串。在这种情况下,我强烈建议在其中使用常规字符(UTF-8)。否则,通过翻译文件维护本地化,甚至读取 - 想想非拉丁文脚本中的语言! - 将会是地狱。

是的,这意味着你必须弄清楚输入方法,但解决方案是干净和直接的。

答案 2 :(得分:1)

如果您不希望通过简单地将.html_safe(通过alias_method_chain或w / e)添加到所有内容来揭露错误的可能性,那么最好的解决方案就是在必要时使用它。

在我们的网站中,我们使用标记语言从i18n语言环境文件中获取HTML输出,因为谁翻译这些文件不是开发人员,只是翻译人员。

如果只是在几个地方你需要你的HTML真的是HTML,请使用.html_safe

t('views.signup.organisation_details').html_safe

我们使用的简单标记语言非常适合我们,但这确实是特定于案例的:)

答案 3 :(得分:0)

您是否了解可以在帮助程序中使用的html_safe方法?我不确定我是否完全理解这里的问题,因为我从未使用过I18n,但是可以使用自定义助手确定字符是否不应该被转义并返回“string”.html_safe,如果它应该被转义,返回“字符串”。

或者可能覆盖“t”帮助器并添加转义逻辑条件+ .html_safe

答案 4 :(得分:0)

我认为使用“raw”不是一个好主意,你可以尝试使用yml这样的字符串

en:
  hello:
    This generates a text paragraph for HTML. " " à @ ' All this text, which you can find in
    these lines, is being concatenated together to one single text node, and then put
    into the body of the <p> ... </p> tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕

HTML

This generates a text paragraph for HTML. &quot; &quot; à @ ' All this text, which you can find in these lines, is being concatenated together to one single text node, and then put into the body of the &lt;p&gt; ... &lt;/p&gt; tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕

浏览器视图

This generates a text paragraph for HTML. " " à @ ' All this text, which you can find in these lines, is being concatenated together to one single text node, and then put into the body of the <p> ... </p> tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕