Как правильно кодировать встроенный объект JavaScript, чтобы защитить его от XSS? - PullRequest
13 голосов
/ 16 августа 2010

Оказывается, что следующий код, похожий на действительный javascript, не является:

<html> 
<body>
<script>
 json = {test: "</script><script>alert('hello');</script>"};
</script>
</body>
</html>

Тот же текст, когда возвращается JSON через ajax api, работает так же, как и ожидалось. Однако при рендеринге in-line возникают базовые проблемы XSS.

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

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

json = {test: "<\/script><script>alert('hello');<\/script>"};

То есть я понятия не имею, как моя базовая библиотека кодирует символ /, возможно, она решила кодировать его, а может и нет. (так что, скорее всего, исправление регулярных выражений более надежно)

Ответы [ 5 ]

5 голосов
/ 17 августа 2010

См. Руководство по предотвращению XSS OWASP (См. Правило № 3) -

За исключением буквенно-цифровых символов, экранируйте все символы меньше 256 в формате \ xHH, чтобы предотвратить переключениезначения данных в контекст скрипта или в другой атрибут.Не используйте экранирующие ярлыки, такие как \ ", потому что символ кавычки может соответствовать парсеру атрибутов HTML, который запускается первым.

Предположим, что ваш объект выглядит так -


var log = {
trace: function(m1, m2, m3){},
debug: function(m1, m2, m3){},
currentLogValue : "trace {].a23-%\/^&",
someOtherObject : {someKey:"somevalue", someOtherKey:"someothervalue"}
};

Это должно закончиться так -


var log = {
trace : "function\x28m1,\x20m2,\x20m3\x29\x7B\x7D",
debug : "function\x28m1,\x20m2,\x20m3\x29\x7B\x7D",
currentLogValue : "trace\x20\x7B\x5D.a23\x2D\x25\x5C\x2F\x5E\x26",
someOtherObject : {someKey : "somevalue", someOtherKey:"someothervalue"}
};

Правила просты -

  1. Ненадежные данные допускаются только в паре кавычек
  2. Независимо от того, чтов кавычках экранируется следующим образом: «За исключением буквенно-цифровых символов, экранируйте все остальное в формате \ xHH»

Это гарантирует, что ненадежные данные всегда интерпретируются как строка, а не как функция / объект /все остальное.

4 голосов
/ 16 августа 2010

Начнем с того, что это вообще не JSON, это объект Javascript. JSON - это текстовый формат, основанный на синтаксисе Javascript.

Вы можете убедиться, что код не содержит комбинацию символов </:

var obj = { test: "<"+"/script><script>alert(\"hello\");<"+"/script>" };

Или, если вы используете XHTML, вы можете убедиться, что содержимое тега script интерпретируется как простые данные:

<script type="text/javascript">
//<![CDATA[
var obj = { test: "</script><script>alert(\"hello\");</script>" };
//]]>
</script>
2 голосов
/ 25 августа 2010

Одна из проблем, с которой вы можете столкнуться, заключается в том, что интерпретаторы HTML и javascript в браузере запускаются с чередованием.

<html> 
<body>
<script>
 json = {test: "</script><script>alert('hello');</script>"};
</script>
</body>
</html>

В вашем примере интерпретатор HTML выдаст json = {test: " интерпретатору jsи затем он найдет следующий блок javascript (ограниченный тегами <script> и </script>) и передаст alert('hello'); интерпретатору js.Неважно, что тег </script> находится в строке javascript, потому что интерпретатор HTML ищет блоки кода js и не понимает строки js.

Первый раздел вызовет jsсинтаксическая ошибка, в то время как второй раздел создаст предупреждение.Я понимаю, что это не ответит на ваш вопрос о том, что делать, но, возможно, это позволит пролить больше света на то, что происходит под капотом.

2 голосов
/ 16 августа 2010

В буквальных строках ставьте обратную косую черту (\) перед всеми «небезопасными» символами, включая косую черту, которая встречается в «</script>» (/\/).

Это изменит ваш пример на:

json = {test: "<\/script><script>alert(\"hello\");<\/script>"};

, и все равно будет действительным JSON.

Конечно, вы также должны избегать двойной кавычки ("\")и саму обратную косую черту (\\\), но вам все равно придется это делать.Вам также следует рассмотреть возможность избежать одиночной кавычки ('\'), чтобы быть в безопасности.

1 голос
/ 16 августа 2010

Я нашел этот список символов для экранирования строк JSON:

\b  Backspace (ascii code 08)
\f  Form feed (ascii code 0C)
\n  New line
\r  Carriage return
\t  Tab
\v  Vertical tab
\'  Apostrophe or single quote
\"  Double quote
\\  Backslash character

Использование PHP? Если так: json_encode

 echo json_encode("<\/script><script>alert(\"hello\");<\/script>");

Выход:

 "<\\\/script><script>alert(\"hello\");<\\\/script>"

Другой пример:

 echo json_encode("</script><script>alert(\"hello\");</script>");

Выход:

 "<\/script><script>alert(\"hello\");<\/script>"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...