ES2015模板字符串安全问题

时间:2016-01-21 22:58:25

标签: javascript security ecmascript-6

以下是MDN的引用:

  

模板字符串绝不能由不受信任的用户构建,因为它们可以访问变量和函数。

一个例子:

`${console.warn("this is",this)}`; // "this is" Window

let a = 10;
console.warn(`${a+=20}`); // "30"
console.warn(a); // 30

此处的示例并未显示我可以看到的任何漏洞。

任何人都可以举一个利用这个漏洞利用的例子吗?

2 个答案:

答案 0 :(得分:9)

这没有任何意义。模板字符串无法访问任何内容,也不会执行。模板字符串是该语言的语法元素。

动态构建模板字符串是没有问题的 - 它就像构建表达式(无论是什么格式,无论是代码字符串还是AST)。 MDN提示的问题是评估这样的表达式(例如使用eval,将其序列化为提供给用户的脚本等) - 它可能包含任意代码,与字符串文字相反!但是你当然不会这样做,不是吗?

此警告类似于说" 使用+运算符的连接不能由不受信任的用户构建,因为它们可以访问变量和函数。"并为其提供示例"" + console.warn("this is",this) + ""。嗯,这对于语言的任何表达都是如此,所以它不是特别有趣。

虽然我们在谈论糟糕的编码,但当然有一种情况是使用模板字符串(嘿,它们是多线和诸如此类的)而不是字符串文字可能会导致问题:

function escapeString(str) {
    return JSON.stringify(str).slice(1, -1)
           .replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
}

// This is (kinda) fine!
var statement = 'var x = "Hello,\\n'+escapeString(userInput)+'";';
eval(statement); // some kind of evaluation

// But this is not:
var statement = 'var x = `Hello,\n'+escapeString(userInput)+'`;';
//                       ^                                   ^

现在假设userInput包含${…} - 我们没有逃脱......

答案 1 :(得分:0)

我认为@Bergi是正确的 - 这里的危险涉及使用eval或类似的方法来允许用户构建实际的模板字符串,而不是替换。

漏洞利用示例:懒惰的开发人员希望允许用户在其评论中执行一些字符串替换,例如:在像SO这样的网站上引用其他用户或问题。他没有为此开发令牌,而是进行适当的解析和替换,而是决定接受这样的语法:

"I think ${firstPoster} is an idiot! See ${question(1234)} for details!"

并通过以下函数运行它:

var firstPoster = {...};
function question() {...}

processInput(input) {
  return eval('`' + input + '`');
}

如果此代码在客户端上为eval并显示给其他用户,则恶意用户可能会发出XSS次攻击。如果服务器上有eval,则攻击者可以控制该计算机。