Как вставить произвольный JSON в тег скрипта HTML

Я хотел бы сохранить содержимое JSON в источнике документа HTML внутри тега скрипта.

Содержимое этого JSON зависит от введенного пользователем ввода, поэтому для дезинфекции этой строки для XSS требуется большая осторожность.

Я прочитал здесь две концепции SO.

1. Замените все вхождения </script в <\/script или замените все </ in <\/ server side.

Код мудрый выглядит следующим образом (с использованием Python и jinja2 для примера):

 // view data = { 'test': 'asdas</script><b>as\'da</b><b>as"da</b>', } context_dict = { 'data_json': json.dumps(data, ensure_ascii=False).replace('</script', r'<\/script'), } // template <script> var data_json = {{ data_json | safe }}; </script> // js access it simply as window.data_json object 

2. Кодировать данные в виде строки JSON, кодированной в HTML, и unescape + анализировать ее на стороне клиента. Unescape из этого ответа: https://stackoverflow.com/a/34064434/518169

 // view context_dict = { 'data_json': json.dumps(data, ensure_ascii=False), } // template <script> var data_json = '{{ data_json }}'; // encoded into HTML entities, like &lt; &gt; &amp; </script> // js function htmlDecode(input) { var doc = new DOMParser().parseFromString(input, "text/html"); return doc.documentElement.textContent; } var decoded = htmlDecode(window.data_json); var data_json = JSON.parse(decoded); 

Этот метод не работает, потому что \" в источнике скрипта becames " в переменной JS. Кроме того, он создает гораздо больший HTML-документ, а также на самом деле не читается на людях, поэтому я бы пошел первым, если это не означает огромный риск для безопасности.

Есть ли риск безопасности при использовании первой версии? Достаточно ли санировать закодированную строку JSON с .replace('</script', r'<\/script') ?

Ссылка на SO:
Лучший способ хранения JSON в атрибуте HTML?
Зачем расколоть тэг <script> при написании его с помощью document.write ()?
Тэг скрипта в строке JavaScript
Санизировать содержимое элемента <script>
Escape </ in содержимое тега скрипта

Некоторые большие внешние ресурсы по этой проблеме:
tojson фильтра tojson
Метод и источник метода json_escape
5-летняя дискуссия в формате Django и предлагаемый код

Прежде всего, ваша паранойя хорошо обоснована 🙂

  • HTML-Parser может быть обманут закрывающим тегом скрипта (лучше предположить любым закрывающим тегом )
  • JS-Parser может быть обманут обратными косыми чертами и кавычками (с очень плохим кодировщиком)

ДА Было бы намного «безопаснее» кодировать все символы, которые могли бы смутить различных вовлеченных парсеров. Сохранение его правдоподобности может противоречить вашей парадигме безопасности.

НО ЗАМЕЧАНИЕ . Результат кодирования JSON String должен быть каноническим и OFC, а не сломанным, как в parsable. JSON является подмножеством JS и, таким образом, может быть JS разборчивым без какого-либо риска. Таким образом, все, что вам нужно сделать, это убедиться, что экземпляр HTML-Parser, который извлекает JS-код, не обманут вашими пользовательскими данными.

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

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

Как и в: предлагая парсеру, что тег скрипта закончился неявно .

Поэтому рекомендуется кодировать косую черту и все привязки тегов (/, <,>) , а не только закрытие тега-скрипта в любом обратимом методе, который вы выберете, до тех пор, пока он не будет путать HTML-Parser: – Лучшим выбором будет base64 (но вы хотите более читабельны) – HTML будут делать, хотя и запутывают людей 🙂 – Выполнение собственного экранирования также будет работать, просто избегайте отдельных символов, а не

В заключение, да, это, вероятно, лучший 1. с небольшими изменениями. Но учтите, что вы уже на шаг от «безопасного», попробовав что-то вроде этого в первую очередь, вместо того, чтобы загружать JSON через XHR или, по крайней мере, с помощью строгой кодировки строк, такой как base64.

PS: Если вы можете узнать из кодировки кода другого ppl строки, которые хороши, но вы не должны прибегать к «библиотекам» или другим функциям ppl, если они не выполняют именно то, что вам нужно. Так что напишите и тщательно протестируйте свой собственный (de / en) кодер и узнайте, что эта ловушка была запечатана.