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?
3 Réponses :
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);
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()); });
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); }