Échapper des entités HTML dans des littératures de chaîne JavaScript dans le bloc <script>

D'une part, si j'ai

<script> var s = 'Hello </script>'; console.log(s); </script> 

Le navigateur terminera tôt le bloc <script> et, fondamentalement, je fermerai la page.

D'autre part, la valeur de la chaîne peut provenir d'un utilisateur (par exemple, via un formulaire soumis précédemment, et maintenant la chaîne finit par être insérée dans un bloc <script> comme un littéral), donc vous pouvez vous attendre à quelque chose dans ce Chaîne, y compris les étiquettes formées malicieusement. Maintenant, si j'échappe à la chaîne littérale avec htmlentities () lors de la génération de la page, la valeur de s contiendra littéralement les entités échappées, c'est-à-dire que S produira

 Hello &lt;/script&gt; 

Ce qui n'est pas souhaitable dans ce cas.

L'une des façons d'échapper correctement aux chaînes JS dans un bloc <script> échappe à la barre oblique si elle suit le bracket angulaire gauche, ou tout simplement en échappant à la barre oblique, c'est-à-dire

 var s = 'Hello <\/script>'; 

Cela semble fonctionner correctement.

Ensuite, il s'agit de la question du code JS dans les gestionnaires d'événements HTML, qui peut être facilement cassé, par exemple

 <div onClick="alert('Hello ">')"></div> 

Semble valable au début, mais brise la plupart (ou tous les) navigateurs. Ceci nécessite évidemment l'encodage intégral de l'entité HTML.

Ma question est la suivante: quelle est la meilleure pratique standard pour couvrir correctement toutes les situations ci-dessus – c'est-à-dire JS dans un bloc de script, JS dans les gestionnaires d'événements – si votre code JS peut être partiellement généré du côté du serveur et peut contenir potentiellement des données malveillantes?

Les caractères suivants pourraient interférer avec un analyseur HTML ou Javascript et devraient être échappés dans des littéralités de chaînes: <, >, ", ', \, et & .

Dans un bloc de script utilisant le caractère d'échappement, comme vous l'avez découvert, fonctionne. La méthode de concaténation ( </scr' + 'ipt>' ) peut être difficile à lire.

 var s = 'Hello <\/script>'; 

Pour le Javascript en ligne en HTML, vous pouvez utiliser les entités:

 <div onClick="alert('Hello &quot;>')">click me</div> 

Demo: http://jsfiddle.net/ThinkingStiff/67RZH/

La méthode qui fonctionne dans les deux blocs <script> et Javascript en ligne est \uxxxx , où xxxx est le code de caractère hexadécimal.

  • <\u003c
  • >\u003e
  • "\u0022
  • '\u0027
  • \\u005c
  • &\u0026

Demo: http://jsfiddle.net/ThinkingStiff/Vz8n7/

HTML:

 <div onClick="alert('Hello \u0022>')">click me</div> <script> var s = 'Hello \u003c/script\u003e'; alert( s ); </script> 

(Éditer – d'une certaine manière, vous n'avez pas remarqué que vous avez mentionné slash-escape dans votre question déjà …)

OK afin que vous sachiez comment échapper à une barre oblique.

Dans les gestionnaires d'événements en ligne, vous ne pouvez pas utiliser le caractère délimitant à l'intérieur d'un littéral, alors utilisez l'autre:

 <div onClick='alert("Hello \"")'>test</div> 

Mais tout cela contribue à rendre votre vie difficile. N'utilisez pas les gestionnaires d'événements en ligne! Ou si vous devez absolument, demandez-leur d'appeler une fonction définie ailleurs.

D'une manière générale, il y a peu de raisons pour lesquelles votre code côté serveur est en cours d'écriture javascript. Ne génère pas de scripts du serveur – passez des données à des scripts pré-écrits à la place.

(original)

Vous pouvez échapper à quelque chose dans un littéral de chaîne JS avec une barre oblique inverse (ce qui n'est pas autrement un caractère d'échappement spécial):

 var s = 'Hello <\/script>'; 

Cela a également l'effet positif de ne pas l'interpréter comme html. Donc, vous pourriez faire une couverture remplacer "/" par "\ /" à aucun effet négatif.

D'une manière générale, cependant, je crains que les données envoyées par l'utilisateur ne soient incorporées comme un littéral de chaîne en javascript. Vous créez un code javascript sur le serveur? Pourquoi ne pas simplement passer des données en tant que JSON ou un attribut "données" HTML ou quelque chose à la place?

Je dirais que la meilleure pratique serait d' éviter les JS en ligne en premier lieu .

Mettez le code JS dans un fichier séparé et incluez-le avec l'attribut src

 <script src="path/to/file.js"></script> 

Et l'utiliser pour définir les gestionnaires d'événements de l'intérieur est au lieu de mettre ceux dans le HTML.

 //jquery example $('div.something').on('click', function(){ alert('Hello>'); }) 

Voici comment je le fais:

 function encode(r){ return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"}) } var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!'; test.value=encode(myString); testing.innerHTML=encode(myString); /************* * \x26 is &ampersand (it has to be first), * \x0A is newline, *************/ 
 <textarea id=test rows="9" cols="55"></textarea> <div id="testing">www.WHAK.com</div> 

La plupart des gens utilisent cette astuce:

 var s = 'Hello </scr' + 'ipt>';