2

使用最新的主干和下划线库 (1.0.0/1.4.4) 我无法弄清楚为什么我的模板没有像我预期的那样转义。这是一个简化版本:

M = Backbone.Model.extend({});
V = Backbone.View.extend({
    template: _.template("<%- attr %>"),
    render: function() {
        this.$el.html(this.template(this.model.attributes));
        return this;
    }
});
m = new M({attr: "<script>bad</script>"});
v = new V({model: m});
v.render();
console.log(v.el);

结果是:

<div><script>bad</script></div>

显然,这并没有逃脱。我已经验证了作为独立代码执行的模板可以正确转义:

T = _.template("<%- attr %>");
console.log(T({attr: "<script>bad</script>"}));

产生预期的结果

&lt;script&gt;bad&lt;&#x2F;script&gt;

因此,某处的内容没有转义。如果有人知道在哪里,或者更好的是如何防止它,我将不胜感激。

斯蒂芬


更新:

弄清楚了!尽管问题不在于控制台本身,但mu的回答确实为我指明了正确的方向。为了解释,我需要对上面的示例代码进行一些详细说明,以便它更准确地反映我的上下文。该上下文实际上不是控制台输出,而是单元测试。我想验证我的代码是否正确地防止了 XSS 攻击,所以我编写了单元测试(使用 mocha/sinon/chai/should):

v.$el.text().should.equal(m.escape("attr"));

该测试失败(出乎意料),而以下测试通过(我认为它不应该):

v.$el.text().should.equal(m.get("attr"));

罪魁祸首原来是toString()元素对象上的方法。该方法console.log()使用,对内容进行转义。text()jQuery 在函数中也(间接)使用了该方法。

我不确定这在所有浏览器中是否通用,但在我的情况下,使用.innerHTML()可以避免toString()转义。所以写我的测试的正确方法是

v.el.innerHTML().should.equal(m.escape("attr"));
4

1 回答 1

3

我认为您的控制台过于“有用”并使您感到困惑。如果我们仔细观察,我们会确切地看到这里有什么样的诡计;我将切换到<b>而不是<script>避免将其分解<script>成碎片以避免混淆 jsfiddle。

考虑一下:

M = Backbone.Model.extend({});
V = Backbone.View.extend({
    template: _.template("<%- attr %>"),
    render: function() {
        this.$el.html(this.template(this.model.attributes));
        return this;
    }
});
m = new M({attr: "<b>bad</b>"});
v = new V({model: m});
v.render();

$('body').append(v.el);
$('body').append($(v.el).text()).append('<br>');
$('body').append($(v.el).html());

您将在页面上看到三件事:

  1. 一个字面量<b>bad</b>
  2. Abad粗体。
  3. 一个字面量<b>bad</b>

这正是我们期望看到的attr是否被转义。

但是,您正在查看控制台。所以让我们也看看控制台,并在上面的 JavaScript 底部扔了几件事:

console.log(v.el);
console.log(v.el.innerHTML);

现在在控制台中我们看到:

<div><b>bad</b></div>
&lt;b&gt;bad&lt;/b&gt;

但是仔细看第一行,你应该看到<div>and</div>出现在紫色(或者你的控制台用于 DOM 元素的任何高亮颜色),而<b>bad</b>是黑色的(或者你的控制台用于纯文本的任何颜色)。因此,attr正在正确转义,但您的控制台在显示之前正在解码内容。

演示:http: //jsfiddle.net/ambiguous/5nYTd/

于 2013-03-20T20:25:40.820 回答