Экранирование HTML-сущностей в строковых литералах JavaScript внутри блока <script> - PullRequest
26 голосов
/ 06 января 2012

С одной стороны, если у меня есть

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

браузер прекратит блокировку <script> на ранней стадии, и в основном я испортил страницу.

С другой стороны, значение строки может исходить от пользователя (скажем, через ранее отправленную форму, и теперь строка в итоге вставляется в блок <script> как литерал), так что вы можете ожидать что-нибудь в этой строке, включая злонамеренно сформированные теги. Теперь, если при создании страницы я экранирую строковый литерал с помощью htmlentities (), значение s будет содержать буквально экранированные сущности, то есть s будет выводить

Hello &lt;/script&gt;

, что в данном случае нежелательное поведение.

Один из способов правильного экранирования строк JS в блоке <script> - избежать косой черты, если она следует за левой угловой скобкой, или просто всегда избегать косой черты, т.е.

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

Кажется, это работает нормально.

Затем встает вопрос о коде JS в обработчиках событий HTML, который также может быть легко взломан, например,

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

поначалу выглядит корректно, но ломается в большинстве (или во всех?) Браузерах. Это, очевидно, требует полной кодировки сущности HTML.

Мой вопрос: какова наилучшая / стандартная практика для надлежащего охвата всех вышеперечисленных ситуаций - например, JS в блоке сценария, JS в обработчиках событий - если ваш JS-код может быть частично сгенерирован на стороне сервера и потенциально может содержать вредоносные данные?

Ответы [ 5 ]

40 голосов
/ 06 января 2012

Следующие символы могут мешать анализатору HTML или Javascript и должны быть экранированы в строковых литералах: <, >, ", ', \, и &.

В блоке скрипта, как вы узнали, работает escape-символ.Метод конкатенации (</scr' + 'ipt>') может быть сложным для чтения.

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

Для встроенного JavaScript в HTML вы можете использовать сущности:

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

Демонстрация: http://jsfiddle.net/ThinkingStiff/67RZH/

Метод, который работает в обоих <script> блокаха встроенный Javascript - \uxxxx, где xxxx - шестнадцатеричный код символа.

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

Демонстрация: http://jsfiddle.net/ThinkingStiff/Vz8n7/

HTML:

<div onClick="alert('Hello \u0022>')">click me</div>

<script>
    var s = 'Hello \u003c/script\u003e';
alert( s );
</script>   
2 голосов
/ 26 июля 2015

Вот как я это делаю:

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>
2 голосов
/ 06 января 2012

(изменить - как-то не заметил, что вы уже упоминали косую черту в своем вопросе ...)

ОК, так что вы знаете, как избежать косой черты.

Встроенные обработчики событийВы не можете использовать ограничивающий символ внутри литерала, поэтому используйте другой:

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

Но все это помогает усложнить вашу жизнь.Только не используйте встроенные обработчики событий!Или, если вам абсолютно необходимо, попросите их вызвать функцию, определенную в другом месте.

Вообще говоря, у вашего серверного кода мало причин писать код на JavaScript.Не генерируйте сценарии с сервера - вместо этого передавайте данные в предварительно написанные сценарии.

(оригинал)

Вы можете экранировать все, что находится в строковом литерале JS, с обратной косой чертой (что не является иначеспециальный escape-символ):

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

Это также имеет положительный эффект, так как его не следует интерпретировать как html.Таким образом, вы могли бы сделать полную замену «/» на «\ /», чтобы безрезультатно.

В общем, я обеспокоен тем, что вы бы добавили данные, представленные пользователем, как строковый литерал в javascript.Вы генерируете код JavaScript на сервере?Почему бы просто не передать данные в виде JSON или HTML-атрибута «data» или чего-то еще?

2 голосов
/ 06 января 2012

Я бы сказал, что лучшей практикой было бы избегать встроенного JS в первую очередь .

Поместите код JS в отдельный файл и включите его с атрибутом src

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

и используйте его для установки обработчиков событий изнутри вместо помещения их в HTML.

//jquery example
$('div.something').on('click', function(){
    alert('Hello>');
})
0 голосов
/ 06 января 2012

Большинство людей используют этот трюк:

var s = 'Hello </scr' + 'ipt>';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...