Каков наилучший способ обработки созданного пользователем html-контента, который будет просматриваться публикой?

В моем веб-приложении я разрешаю публиковать контент, сгенерированный пользователями, для общественного потребления, аналогичного Stackoverflow.

Какова наилучшая практика для этого?

Мои текущие шаги для обработки созданного пользователем контента:

  • Я использую MarkItUp, чтобы пользователи простой способ отформатировать html.

  • После того как пользователь подал заявку изменения Я запускаю его через HTML Sanitizer (прокрутите страницу до Bottem), который использует белый список подход.

  • Если процесс санитарии удалено любое созданное пользователем содержимое I не сохраняйте содержимое. Затем я Верните туда измененный контент с помощью предупреждающее сообщение: "Некоторые незаконные теги контента, где обнаружены и удалите двойную проверку своей работы и повторите попытку ".

  • Если содержимое проходит через очистка, чистота, сохранение содержимое raw html для базы данных.

  • При рендеринге клиенту я просто передать сырой html из db в страница.

Ответ 1

Это вполне разумный подход. Для типичных приложений это будет вполне достаточно.

Самая сложная часть необработанного HTML белого списка - это атрибут style и embed/object. Существуют законные причины, по которым кто-то может захотеть поместить стили CSS в ненадежный блок форматированного текста или, скажем, встроенное видео YouTube. Эта проблема чаще всего встречается с фидами. Вы не можете доверять произвольному блоку текста, содержащемуся в записи фида, но вы не хотите выделять, например, синтаксис, выделяющий CSS или флеш-видео, потому что это в корне изменит контент и потенциально смутит любого, кто его прочитает. Поскольку CSS может содержать опасные вещи, такие как поведение в IE, вам может потребоваться проанализировать CSS, если вы решите разрешить атрибут style оставаться. И с помощью embed/object вам могут потребоваться имена узлов белого списка.

Addenda:

В худшем случае, сценарии, HTML, избегающий всего в поле зрения, может привести к очень плохому пользователю. Гораздо лучше использовать что-то вроде одного из парсеров HTML5, чтобы пройти через DOM со своим "белым списком". Это намного более гибко с точки зрения того, как вы представляете выработанную продукцию пользователям. Вы можете даже делать такие вещи, как:

<div class="sanitized">
  <div class="notice">
    This was sanitized for security reasons.
  </div>
  <div class="raw"><pre>
    &lt;script&gt;alert("XSS!");&lt;/script&gt;
  </pre></div>
</div>

Затем скройте элемент .raw с помощью CSS и используйте jQuery для привязки обработчика кликов к .sanitized div, который переключает между .raw и .notice:

CSS

.raw {
  display: none;
}

JQuery

$('.sanitized').click(function() {
  $(this).find('.notice').toggle();
  $(this).find('.sanitized').toggle();
});

Ответ 2

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

Самый безопасный метод:

  • HTML кодирует весь текст.

  • Сопоставьте набор допустимых тегов и атрибутов и декодируйте их.

Используя регулярное выражение, вы даже можете потребовать, чтобы у каждого открывающего тега был закрывающий тег, так что незакрытый тег не может испортить страницу.

Вы должны иметь возможность сделать это примерно в десяти строках кода, поэтому код, с которым вы связаны, кажется слишком сложным.