Я хочу сохранить содержимое JSON в источнике документа HTML внутри тега скрипта.
Содержимое этого JSON зависит от ввода, введенного пользователем, поэтому необходимо тщательно обработать эту строку для XSS.
Я прочитал две концепции здесь, на SO.
1. Замените все вхождения тега </script
в <\/script
или замените все </
на стороне сервера <\/
.
Код выглядит следующим образом (с использованием 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 от этого ответа: qaru.site/info/65908/...
// view
context_dict = {
'data_json': json.dumps(data, ensure_ascii=False),
}
// template
<script>
var data_json = '{{ data_json }}'; // encoded into HTML entities, like < > &
</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);
Этот метод не работает, поскольку \"
в источнике сценария становится "
в переменной JS. Кроме того, он создает намного больший HTML-документ, а также не очень удобочитаемый для человека, поэтому я бы остановился на первом, если это не означает огромный риск для безопасности.
Есть ли угроза безопасности при использовании первой версии? Достаточно ли санировать JSON-кодированную строку с помощью .replace('</script', r'<\/script')
?
Ссылка на SO:
Лучший способ сохранить JSON в атрибуте HTML?
Зачем разбивать скрипт & lt; script & gt; тег при записи с помощью document.write()?
Тег скрипта в строке JavaScript
Дезинфицировать & lt; script & gt; содержимое элемента
Escape & lt;/в содержимом тега скрипта
Несколько замечательных внешних ресурсов по этой проблеме:
Реализация фильтра Flask tojson
source
Rail json_escape
метод справки и источника
5-летнее обсуждение в Django тикете и предложенном коде