Les modèles ES6 sont-ils plus sûrs que eval?

Les mots-clés des modèles me sentent un peu comme eval, et il est souvent cité que l' utilisation d'eval est une mauvaise idée .

Je ne me préoccupe pas de l' exécution des modèles littéraires , mais je suis préoccupé par les attaques par injection (et d'autres problèmes de sécurité, je ne pense peut-être pas).

modifier

Un exemple de quelque chose qui me paraît étrange

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

Quelles sorties

1, 2, 3

Le modèle littéral fait des effets secondaires au niveau mondial. Tous deux par une fonction, et directement.

Modifier 2

Un exemple indiquant la sécurité des modèles littéraires

 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); 

Si vous indiquez ii++ lorsque vous y êtes invité, il enregistre

Démarrage: 1

Vous entrez: ii + = 1

Après le modèle literal: 1

Après eval: 2

Modifier 3

J'ai commencé à examiner la spécification ECMAScript

  • 18.2.1 – Fonction Propriétés de l'objet global :: Eval (x)
    • Remarquez qu'il est sur l'objet global
    • Remarquez que la prochaine section porte sur 'Runtime Semantics' de eval
  • 12.2.9 – Expression primaire :: Littérature de modèle
    • Remarquez que c'est une expression
    • Notez que la section suivante porte sur «Sémantique statique» de TemplateStrings

Bien que je n'échappe pas aux détails, il me semble que les littéraux de modèle sont spécifiés plus sûrs que eval.

Une différence avec eval est que les littéraux de modèle sont analysés au moment de la compilation, alors que l'argument d' eval est analysé uniquement au moment de l'exécution, lorsque eval est exécuté.

En ce qui concerne ceci, est-ce que eval peut obtenir un argument construit dynamiquement, alors qu'un modèle littéral est … littéral : il ne peut pas être stocké en tant que variable de modèle, que vous pouvez construire dynamiquement, se déplacer et finalement analyser: il n'y a pas de "modèle Variable "type de données. Une fonction de balise n'obtient pas réellement une variable de modèle comme argument, mais les composants analysés, connus au moment de la compilation.

Quelques exemples

Avec eval vous pouvez avoir cette situation:

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

Mais ce n'est pas possible avec les modèles littéraires:

 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. 

Ce qui est possible, c'est ceci:

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

Mais cela ne conduit pas à une exécution de code indésirable, du moins pas pire que cela:

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

Les appels de fonction doivent déjà être encodés littéralement dans un modèle littéraire. Les valeurs des variables de chaîne ne peuvent pas changer cela. Il n'y a aucun moyen pour lequel une fonction variable est appelée par un modèle littéraire. Ce:

 `${func(str)}`; 

… appellera func , et cette fonction seulement. Il est choisi par le programmeur.

Un modèle littéral plutôt maléfique

Cela dit, cela est encore possible:

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

Les mots-clés des modèles échappent à des guillemets automatiquement, si cela vous préoccupe. Ils n'évalurent pas non plus ou n'exécutent rien, ils convertissent tout ce que vous mettez en chaîne. Si vous êtes préoccupé par SQL Injection, essayez de le faire avec des littéraux de modèle et vous verrez qu'ils se sont échappés.

Vous devriez éviter d'utiliser eval, sauf si vous avez une très bonne raison de l'utiliser et vous savez vraiment que vous en avez besoin pour atteindre votre objectif. Sinon, il est préférable d'éviter .

Je pense qu'il y a une grande différence entre eval et les modèles littéraires .

Eval peut évaluer des expressions dynamiques qui ne sont pas directement visibles à partir du code. Cela rend dangereux, car vous pouvez évaluer n'importe quelle chaîne pouvant venir de n'importe où: client / tiers / db …

Cependant, la situation est différente dans le cas des modèles littéraires ,

  • Car vous pouvez voir le modèle complet à partir du code,
  • Les expressions fonctionnent avec vos objets internes et ne peuvent pas évaluer l'expression dynamique.

Par exemple, cela fonctionnera avec eval

 function doSomething() { console.log('HELLO!'); } // This will work. var expression = 'doSomething()'; eval(expression);