Какова максимальная глубина документов HTML на практике? - PullRequest
22 голосов
/ 14 октября 2011

Я хочу разрешить встраивание HTML, но избегать DoS из-за глубоко вложенных HTML-документов, которые приводят к сбоям в некоторых браузерах.Я хотел бы иметь возможность разместить 99,9% документов, но отклонить те, которые вкладываются слишком глубоко.

Два тесно связанных вопроса:

  1. Какие ограничения глубины документа встроены в браузеры?Например, браузер X не может выполнить синтаксический анализ или не создает документы с глубиной> некоторого ограничения.
  2. Доступна ли статистика глубины документа для документов в Интернете?Есть ли сайт с веб-статистикой, который объясняет, что некоторый процент реальных документов в Интернете имеет глубину документа меньше некоторого значения.

Глубина документа определяется как 1 + максимальное число родительских обходов, необходимое длядостичь корня документа из любого узла в документе.Например, в

<html>                   <!-- 1 -->
  <body>                 <!-- 2 -->
    <div>                <!-- 3 -->
      <table>            <!-- 4 -->
        <tbody>          <!-- 5 -->
          <tr>           <!-- 6 -->
            <td>         <!-- 7 -->
              Foo        <!-- 8 -->

максимальная глубина равна 8, поскольку текстовый узел "Foo" имеет 8 предков.Предок здесь интерпретируется не строго, то есть когда-либо узел является своим собственным предком и своим потомком.

Opera имеет некоторую статистику вложенности таблиц, которая предполагает, что 99,99% документов имеют вложенность таблицглубина меньше 22, но эти данные не содержат всю глубину документа.

РЕДАКТИРОВАТЬ:

Если люди хотели бы критиковать библиотеку очистки HTML вместо ответа на этот вопрос, пожалуйста, сделайте это.http://code.google.com/p/owasp-java-html-sanitizer/wiki/AttackReviewGroundRules объясняет, как найти код, где найти испытательный стенд, позволяющий вам испытывать атаки, и как сообщать о проблемах.

РЕДАКТИРОВАТЬ:

Я спросил Адама Барта,и он очень любезно указал мне на код webkit, который обрабатывает это.

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

m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document), maximumDOMTreeDepth**(document)))

и проверяется блок-вкладыш тест.

Ответы [ 2 ]

19 голосов
/ 15 октября 2011

Возможно, стоит спросить coderesearch@google.com.Их исследование 2005 года (http://code.google.com/webstats/) не охватывает ваш конкретный вопрос. Тем не менее, они отобрали более миллиарда документов и заинтересованы в том, чтобы услышать обо всем, что, по вашему мнению, стоит изучить.

- [Обновление] -

Вот грубый сценарий, который я написал для проверки имеющихся у меня браузеров (поместив количество элементов для вложения в строку запроса):

var n = Number(window.location.search.substring(1));

var outboundHtml = '';
var inboundHtml = '';

for(var i = 0; i < n; i++)
{
    outboundHtml += '<div>' + (i + 1);
    inboundHtml += '</div>';
}

var testWindow = window.open();
testWindow.document.open();
testWindow.document.write(outboundHtml + inboundHtml);
testWindow.document.close();

И вот мои выводы(может относиться к моей машине, Win XP, 3Gb Ram):

  • Chrome 9: рендерится вложенные элементы 3218, вкладка сбоев 3129. (Chrome 9 старый, я знаю, на моем сбое обновлениякорпоративная локальная сеть)
  • Safari 5: 3477 выполнит рендеринг, браузер 3478 полностью закроется.
  • IE8: 1000000+ выполнит рендеринг (если позволяет память), хотя при значительных четырехзначных числах производительность значительно снижаетсяк появлению пузырьков при прокрутке / перемещении мыши и т. д. Все, что превышает 10000, кажется заблокированным, но я думаю, что просто занимает очень много времени, поэтому эффективна DoS.
  • Opera11: Насколько я могу судить, ограничено только памятью, т.е. моему скрипту не хватает памяти на 10000000. Однако для больших документов, которые визуализируются, не наблюдается никакого снижения производительности, как в IE.
  • Firefox 3.6: ~ 1500000 будет рендериться, но тестирование выше этого диапазона привело к сбою браузера с Mozilla Crash Reporter или просто зависанию, иногда работающее число не получалось в следующий раз, но большие числа ~ 1700000 приводили к сбою Firefox сразу после перезапуска.

Подробнее о Chrome:

Изменение DIV на SPAN привело к тому, что Chrome смог вложить 9202 элементов перед сбоем.Поэтому причина заключается не в размере HTML (хотя элементы SPAN могут быть более легкими). ​​

Вложенные ячейки таблицы 2077 (<table><tr><td>) работали (6231 элемент), пока вы не прокрутили до ячейки 445затем произошел сбой, поэтому вы не можете вложить 445 ячеек таблицы (1335 элементов).

Тестирование с использованием файлов, сгенерированных из сценария (в отличие от записи в новые окна), дает несколько более высокие допуски, но Chrome все еще падает.

Вы можете вложить 1409 элементов списка (<ul><li>) до его сбоя, что интересно , потому что:

  • Firefox останавливает отступ элементов списка после 99,может быть программное ограничение.
  • Opera продолжает отступать с глюками на 250, 376, 502, 628, 754, 880 ...

Установка DOCTYPE эффективна в IE8 (если поставитьв стандартном режиме, то есть var outboundHtml = '<!DOCTYPE html>';): он не будет вкладывать 792 элемента списка (вкладка вылетает / закрывается) или 1593 DIV.В IE8 не имеет значения, был ли тест сгенерирован из сценария или загружен из файла.

Таким образом, предел вложенности браузера, по-видимому, зависит от типа HTML-элементов, внедряемых злоумышленником, и от механизма компоновки.,Там может быть немного HTML значительно меньше, чем этот.И у нас есть обычные DoS в формате HTML для пользователей IE8, Chrome и Safari со значительно меньшей полезной нагрузкой.

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

4 голосов
/ 19 октября 2011

Для webkit максимальная глубина документа настраивается, но по умолчанию она составляет 512

http://trac.webkit.org/browser/trunk/Source/WebCore/page/Settings.h#L408

static const unsigned defaultMaximumHTMLParserDOMTreeDepth = 512;
...