Подтвердить что ты не робот

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

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

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

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

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

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

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

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

EDIT:

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

EDIT:

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

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

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

и он протестирован с помощью теста block-nesting-cap.

4b9b3361

Ответ 1

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

- [Update] -

Здесь грубая script я написал для проверки браузеров, которые у меня есть (поместив количество элементов в строку запроса):

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 сбоев. (Хром 9 старый, я знаю, сбой обновления в моей корпоративной локальной сети)
  • Safari 5: 3477 будет отображаться, браузер 3478 полностью закрывается.
  • IE8: 1000000+ будет выдавать (разрешить память), хотя производительность значительно снижается, когда в высокие 4-значные числа из-за пузыряния события при прокрутке/перемещении мыши/и т.д. Кажется, что что-то более 10000 блокируется, но я думаю, что это занимает очень много времени, так что это эффективная DoS.
  • Opera 11: насколько это возможно, ограничено памятью, то есть у моего script заканчивается память на 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 элементов).

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

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

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

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

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

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