Как мне защититься от XSS / инъекции при использовании jquery.append?

#jquery #append #xss

#jquery #добавить #xss

Вопрос:

Я создаю редактор кода javascript для пользователей на моем сайте. Одной из функций, которые я создал, была пользовательская консоль. Пользователи могут писать console.войдите в их код, и записанная строка будет добавлена к div на странице, делая что-то вроде этого:

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

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

    myconsole.append(message);
}
  

str устанавливается в любую строку, которую вводит пользователь console.log . Может ли добавление этой строки запустить вредоносный код на моей странице? (На странице jQuery api .append() написано «да», но, похоже, я не могу заставить ее интерпретировать все, что я пишу, как html)

Если да, то как я могу предотвратить это и как я могу проверить, чтобы убедиться, что это безопасно?

Ответ №1:

Вы можете использовать text() для вставки содержимого в виде TextNode, что приведет к тому, что страница отобразит его не как разметку, а как обычный текст.

 var stringContainingHtmlAndJavascript = '<div><b>This will be bold</b></div>';

$(document.body).text(stringContainingHtmlAndJavascript);
$(document.body).append(stringContainingHtmlAndJavascript);  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>  

Ответ №2:

Как сказал Таплар, есть разные способы. Вы также можете добавить HTML во временный тег и впоследствии извлечь текст. Смотрите мой третий пример для этого.

 $(function() {
  var stringContainingHtmlAndJavascript = '<div><b>This will be bold</b></div>';

  $('.test1').append(stringContainingHtmlAndJavascript);
  $('.test2').text(stringContainingHtmlAndJavascript);
  $('.test3').text($('<i/>').append(stringContainingHtmlAndJavascript).text());
});  
 <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>  

Ответ №3:

Я предложу вам .parseHTML() использовать bemol, как указано в документации.

.parseHTML() как следует из названия метода, анализирует строку для интерпретации HTML.
Третьему аргументу keepScripts по умолчанию присвоено значение false … Установка значения true широко открыла бы ворота для сценариев.

Таким образом, он «обычно удаляет» теги скрипта. Если HTML или текст вообще не найден, он возвращается undefined (как демонстрационный пример # 3). Таким образом, вам, вероятно, потребуется добавить if условие, чтобы избежать добавления текста «undefined».

Итак… В приведенной ниже демонстрации я использовал ваш опубликованный «скрипт для добавления» как есть… Я только что добавил метод синтаксического анализа HTML.

ВАЖНО, случаи с 1 по 4 безопасны… Но # 5 — это нарушение. Если в анализируемом HTML есть встроенный атрибут on[event], он пройдет через «фильтр сценариев» и может быть выполнен.

 $(".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);
}  
 input{
  width: 60em;
}
#console-text{
  height:8em;
  width:20em;
  background-color: #bbb;
  border: 1px solid black;
}  
 <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>  

   (Пожалуйста, запустите в режиме полной страницы)
CodePen

Вы заметите [0] после $.parseHTML(str) … Это для получения элемента DOM из объекта jQuery, поскольку ваша функция — обычный JS. Ваша функция тоже может быть написана подобным образом (делает то же самое):

 function toConsole(str) {

  str = $.parseHTML(str);

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

  myconsole.append(message);
}
  

Ответ №4:

jquery.append() и jquery.html () не защищены от XSS-атаки, если вы не очистите данные, когда захотите отобразить их пользователю.

 function encodeHTML(s) {
return s.replace(/amp;/g, 'amp;amp;').replace(/</g, 'amp;<').replace(/"/g, 'amp;quot;');}
  

но jquery.text() безопасен, потому что он не отображает html-код и выводит его в необработанном виде.