Шаблон безопасности 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 кодовые точки.

Другие вопросы по тегам