2
votes

Comment se protéger contre XSS / Injection lors de l'utilisation de jquery.append?

Je crée un éditeur de code javascript pour les utilisateurs de mon site. L'une des fonctionnalités que j'ai créées était une console personnalisée. Les utilisateurs peuvent écrire console.log dans leur code et la chaîne enregistrée est ajoutée à un div sur la page en faisant quelque chose comme ceci:

  function toConsole(str) {
    var myconsole = document.getElementById("console-text");

    var message = document.createElement("span");
    message.append(str);

    myconsole.append(message);
}

str est défini sur n'importe quelle chaîne l'utilisateur saisit dans console.log . L'ajout de cette chaîne peut-il exécuter du code malveillant sur ma page? (La page .append () jQuery api dit "oui" mais je n'arrive pas à obtenir pour interpréter tout ce que j'écris en html)

Si oui, comment puis-je éviter cela et comment puis-je tester pour m'assurer que c'est sûr?


0 commentaires

3 Réponses :


1
votes

Vous pouvez utiliser text () pour insérer le contenu en tant que textNode, ce qui ne le fera pas à rendre par la page sous forme de balisage, mais sous forme de texte brut.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
var stringContainingHtmlAndJavascript = '<div><b>This will be bold</b></div>';

$(document.body).text(stringContainingHtmlAndJavascript);
$(document.body).append(stringContainingHtmlAndJavascript);


0 commentaires

0
votes

Comme l'a dit Taplar, il existe différentes manières. Vous pouvez également ajouter le HTML à une balise temporaire et extraire le texte par la suite. Consultez mon troisième exemple pour faire cela.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test1"></div>
<div class="test2"></div>
<div class="test3"></div>
$(function() {
  var stringContainingHtmlAndJavascript = '<div><b>This will be bold</b></div>';

  $('.test1').append(stringContainingHtmlAndJavascript);
  $('.test2').text(stringContainingHtmlAndJavascript);
  $('.test3').text($('<i/>').append(stringContainingHtmlAndJavascript).text());
});


0 commentaires

1
votes

Je vais vous suggérer .parseHTML () avec un bemol , comme indiqué dans la documentation.

.parseHTML () , comme le nom de la méthode l'indique, analyse une chaîne pour interpréter le HTML.
Le troisième argument keepScripts est défini par défaut sur false ... Le définir sur true ouvrirait largement les portes aux scripts.

Donc, "supprime normalement" les balises de script. Si aucun HTML ou texte n'est trouvé, il renvoie undefined (comme le cas de démonstration n ° 3). Vous devrez donc probablement ajouter une condition if pour éviter d'ajouter le texte "undefined".

Alors ... Dans la démo ci-dessous, je utilisé votre "script à ajouter" tout à fait tel quel ... Je viens d'ajouter la méthode d'analyse HTML.

IMPORTANT , les cas n ° 1 à n ° 4 sont sûrs ... Mais le n ° 5 est une violation . S'il y a un attribut inline on [event] dans le HTML analysé, il passera par le "script filter" et pourra s'exécuter.

function toConsole(str) {

  str = $.parseHTML(str);

  var myconsole = $("#console-text");
  var message = $("<span>");
  message.append(str);

  myconsole.append(message);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

console.log test #1:<input class="console_input" value="Just text">
<button class="console_ok">OK</button><br>
<br>
console.log test #2:<input class="console_input" value="<h1>Some HTML</h1>">
<button class="console_ok">OK</button><br>
<br>
console.log test #3:<input class="console_input" value="<script>alert('A script!!!');</script>">
<button class="console_ok">OK</button><br>
<br>
console.log test #4:<input class="console_input" value="<div style='height:20px;background-color:red;'><script>alert('A script!!!');</script>And some <b>bold</b> text...</div>">
<button class="console_ok">OK</button><br>
<br>
console.log test #5:<input class="console_input" value="<img src='invalid-path' onerror='alert(`JS EXECUTES HERE!!!`);'>">
<button class="console_ok">OK</button><br>
<br>

My console:<br>
<div id="console-text"></div>
input{
  width: 60em;
}
#console-text{
  height:8em;
  width:20em;
  background-color: #bbb;
  border: 1px solid black;
}

(Veuillez exécuter en mode page complète)
CodePen

Vous remarquerez le [0] après $ .parseHTML (str) ... C'est pour récupérer l'élément DOM de l'objet jQuery, car votre fonction est du JS pur. Votre fonction pourrait également être écrite comme ceci (fait exactement la même chose) :

$(".console_ok").on("click",function(){
  toConsole( $(this).prev(".console_input").val() );
});

function toConsole(str) {

  str = $.parseHTML(str)[0];

  var myconsole = document.getElementById("console-text");
  var message = document.createElement("span");
  message.append(str);

  myconsole.append(message);
}


0 commentaires