ES6模板文字比eval更安全吗? [英] Are ES6 template literals safer than eval?

查看:193
本文介绍了ES6模板文字比eval更安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

模板文字对我来说有点像eval,而且通常引用使用eval是一个坏主意

Template literals smell a bit like eval to me, and it's often cited that using eval is a bad idea.

我不关心表现模板文字,但我担心注入攻击(和其他安全问题,我可能没有想到)

I'm not concerned with performance of template literals, but I am concerned about injection attacks (and other security concerns I may not be thinking of).

修改

对我感到奇怪的一个例子

let ii = 1;
function counter() {
    return ii++;
}
console.log(`${counter()}, ${ii++}, ${counter()}`);

哪些输出


1,2,3

1, 2, 3

模板文字在全球层面产生副作用。这两个函数都是直接的。

The template literal is making side effects at the global level. Both by a function, and directly.

编辑2

一个示例,表明模板文字的安全性

let ii = 1;
let inc = function() { ii++; }
console.log('Starting: ' + ii);
let input = prompt('Input something evil (suggestion: inc() or ii++)');
console.log(`You input: ${input}`);
console.log('After template literal: ' + ii);
eval(input);
console.log('After eval: ' + ii);

如果在提示时输入 ii ++ 日志


开始:1

Starting: 1

您输入:ii + = 1

You input: ii+=1

模板文字后:1

eval后:2

编辑3

我已经开始研究ECMAScript规范

I've started looking into the ECMAScript specification


  • 18.2.1 - 全局对象的功能属性:: Eval(x)


    • 注意它在全局对象上

    • 请注意下一节是关于eval的<运行时语义>


    • 注意这是一个表达式

    • 注意下一节是关于TemplateStrings的静态语义

    虽然我没有详细说明,感觉像模板文字被指定比eval更安全。

    Though I'm not grokking the details, it feels like template literals are specified safer than eval.

    推荐答案

    eval 是在编译时解析模板文字,而 eval 的参数只在运行时被解析,当 eval 执行

    One difference with eval is that template literals are parsed at compile time, while the argument to eval only gets parsed at run-time, when eval is executed.

    与此相关的是, eval 可以获得动态建立的参数,而模板文字是... 文字:它不能存储为模板变量,您可以动态构建,移动并最终解析:没有模板变量数据类型。标签函数实际上并没有得到一个模板变量作为参数,而是编译时已知的解析的组件。

    Related to this, is that eval can get a dynamically built argument, while a template literal is ... literal: it cannot be stored as a template variable, which you could build dynamically, move around and eventually parse: there is no "template variable" data type. A tag function does not actually get a template variable as argument, but the parsed components of it, which are known at compile-time.

    使用 eval 可以有这种情况:

    var code = prompt('enter some evil code');
    eval(code);
    

    但是,模板文字不可能:

    But that is not possible with template literals:

    var literal = prompt('enter some evil template literal');
    tag literal; // there is no data type or syntax for this.
    `${literal}`; // and this just gives you the entered string.
    

    可能的是,这是:

    var str = prompt('enter some string');
    tag`${str}`;
    

    但是这不会导致不必要的代码执行,至少不会比这更糟糕:

    But that does not lead to unwanted code execution, at least not worse than this:

    var str = prompt('enter some string');
    myfunc(str);
    

    任何函数调用必须在字面上以模板文字形式编码。字符串变量的值不能改变。没有办法通过模板文字调用变量函数。这个:

    Any function calls must already be encoded literally in a template literal. Values of string variables cannot change that. There is no way a variable function gets called by a template literal. This:

    `${func(str)}`;
    

    ...将调用 func ,那个功能只有。它由程序员选择。

    ...will call func, and that function only. It is chosen by the programmer.

    尽管如此,这仍然是可能的:

    Having said that, this is still possible:

    var func = prompt ("enter some evil function name (suggestion: 'alert')");
    var param = prompt ("now provide an argument for " + func);
    
    `${window[func](param)}`;

    但是很明显,程序愿意可以打开在全局对象上执行任何函数的可能性。那么确实,你正在接近 eval 的邪恶。

    But it is evident that the program willingly opens up the possibility to execute any function on the global object. Then indeed, you are getting close to the evilness of eval.

    请注意,同样的效果是:

    Note that the same effect is achieved with:

    window[name](param);
    



    最邪恶的模板文字



    As评论,那么你也可以使这个模板文字:

    The most evil template literal

    As commented, then you might as well make this template literal:

    `eval(str)`;
    

    ...所以邪恶的部分不是在模板文字中,而是通用功能打电话给你设计。为此,您不需要模板文字或 eval ,但不好的程序员; - )

    ... and so the evil part is not so much in the template literal, but the generic function call you have designed to be in it. For that you don't need template literals or eval, but a bad programmer ;-)

    你给了这个例子:

    let ii = 1;
    function counter() {
        return ii++;
    }
    console.log(`${counter()}, ${ii++}, ${counter()}`);
    

    这将执行您的计数器函数,但是与 eval 的区别在于字符串字面值在设计时已经存在,并且无法在运行时构建。这个代码是设计为增加你的计数器,而且与以下不同:

    This executes your counter function, but the difference with eval is that the string literal was already there at design time, and could not have been constructed at run-time. This code is designed to increment your counter, and is not essentially different from:

    console.log(counter() + ', ' + (ii++) + ', ' + counter());
    



    编译时间



    强调差异的编译/运行时解析,请注意,您无法运行不具有有效语法的模板文字的代码。

    Compile Time

    To stress the difference of compile/run time parsing, note that you cannot run code with a template literal that does not have valid syntax.

    比较这两个脚本:

    alert('press OK');
    eval('alert("hello)');
    

    和:

    alert('press OK');
    `${alert("hello)}`;
    

    请注意语法错误。第一个脚本只会在运行时发生语法错误,当 eval 的参数被解析时,第二个脚本甚至不会运行,并立即给出语法错误。

    Note the syntax error. The first script will only notice the syntax error at run-time when the argument to eval is parsed, while the second script will not even run, and give the syntax error immediately.

    更确切地说, eval 执行一个新的脚本,具有自己的编译和运行阶段。模板文字与其他代码一样被解析/编译。

    Put more exactly, eval executes a new script, with its own compile and run phases. A template literal is parsed/compiled like other code.

    这篇关于ES6模板文字比eval更安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆