Шаблон безопасности Pyramid Chameleon для HTML и Javascript
Шаблоны Chameleon экранируют / удаляют теги XSS и HTML для переменных? Будет ли следующее безопасно?
<script type="text/javascript">
var initialComments = ${comments};
for (var i = 0; i < initialComments.length; i++) {
initialComments[i].userId = initialComments[i].user_id;
}
var post = ${post}
// ...
</script>
2 ответа
Это на самом деле сложнее, чем кажется, и зависит от обстоятельств. Если выходным форматом является HTML, то содержимое скрипта представляет собой специальный раздел CDATA, в котором экранирование XML/SGML не интерпретируется. Если выходным форматом является XML с типом содержимого XML, то экранированные символы работают должным образом. Даже если можно было залатать Хамелеона так, чтобы он понимал <script></script>
Элемент как особый, в настоящее время это не так.
Когда встроено в <script>
тег, в зависимости от версии браузера, подошва </
или же </script
завершит тег script, делая его уязвимым для XSS. Кроме того, <
может начать комментарий HTML, как в <!--
и наследственные соображения требуют, чтобы <script></script>
может быть написано сбалансированным внутри тега script, таким образом, наиболее безопасным является <
в целом во всех строках.
Другая проблема заключается в том, что JSON не является строгим подмножеством JavaScript, позволяя символьным строкам, таким как U+2028 и U+2029, ломать скрипт, если вы используете ensure_ascii=False
:
Таким образом, правильный способ сделать это на Python/ хамелеон, чтобы встроить в <script>
тег в HTML должен использовать:
post_json = (json.dumps(foo, ensure_ascii=False)
.replace('\u2028', r'\u2028')
.replace('\u2029', r'\u2029')
.replace('<', r'\u003c'))
Это верно только для контента, встроенного в <script>
теги.
или если вы просто хотите получить нечитаемые экранированные символы практически для всех персонажей, которыми вы можете довольствоваться:
post_json = json.dumps(foo, ensure_ascii=True)\
.replace('<', r'\u003c')
а затем вставлять с
${structure: post_json}
Я разместил запрос функции в трекере ошибок Python, чтобы иметь ключевой аргумент, чтобы сделать это автоматически, но он был отклонен.
Более безопасный способ встраивать вещи - хранить их в data-*
атрибутов.
ОБНОВЛЕНИЕ выхода </
одного недостаточно.
Со страницы введения Хамелеона:
По умолчанию строка экранируется перед вставкой. Чтобы избежать этого, используйте
structure
: префикс
Однако это не ускользнет от значений JavaScript. Используйте для этого JSON; по вашему мнению, используйте:
post_json = (json.dumps(post)
.replace(u'<', u'\\u003c')
.replace(u'>', u'\\u003e')
.replace(u'&', u'\\u0026')
.replace(u"'", u'\\u0027'))
создать HTML-безопасную строку JSON; JSON (как произведено json.dumps()
по крайней мере 1) это подмножество Javascript, здесь с экранированием любых опасных HTML-символов (благодаря Flask json.htmlsafe_dumps()
функция).
Интерполируйте это в ваш шаблон, используя structure
:
<script type="text/javascript">
var initialComments = ${comments};
for (var i = 0; i < initialComments.length; i++) {
initialComments[i].userId = initialComments[i].user_id;
}
var post = ${structure:post_json};
// ...
</script>
1 JSON допускает символы U+2028 и U+2029, но json.dumps()
Функция по умолчанию экранирует все не-ASCII кодовые точки.