问题 ES2015模板字符串安全问题


这是引用 MDN

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

一个例子:

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

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

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

任何人都可以举例说明利用此漏洞的漏洞吗?


3720
2018-01-21 22:58


起源

编辑........ - probablyup
这与模板字符串无关 - Mosho
这是eval()。这已经很危险了。此外,这不是模板字符串。 - Luggage
也许看看谁在MDN上添加评论并问他们为什么? - mikemaccana
你可以问作者 修订 通过 他的推特 详情。 - Bergi


答案:


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

动态构造模板字符串是没有问题的 - 它就像构建一个表达式(无论是什么格式,无论是代码字符串还是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 包含一个 ${…}  - 我们没有逃脱......


9
2018-01-21 23:09



自然。但是,MDN上的示例显示了您在第一段中失效的内容。 - Mosho
@Mosho:无论如何,我在该示例中看不到任何模板字符串的构造 - Bergi
你什么意思?谈论这个: ${console.warn("this is",this)} - Mosho
这是一个模板字符串,其中一部分被表达式的结果替换 console.warn("this is", this)是的但是那个表达式首先是如何实现的呢?不是动态建筑或任何东西。 - Bergi
这就像说“使用连接的连接 + 运算符不能由不受信任的用户构造,因为它们可以访问变量和函数。“举个例子 "" + console.warn("this is",this) + "" - Bergi


我认为@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在服务器上,攻击者可以控制机器。


0
2018-01-21 23:37



虽然此时的问题是模板字符串是最不用担心的。 - Kevin B
这是一种延伸,我怀疑这是作者的意图。 - Mosho
这只是误用 eval() 模板字符串是偶然的。 - Luggage
@KarelG - 好吧,我称他们为“懒惰”,但也许我更好:) - nrabinowitz