tipos - ¿Cuál es la profundidad máxima de los documentos HTML en la práctica?
section html ejemplos (2)
Quiero permitir la incorporación de HTML, pero evitar DoS debido a documentos HTML profundamente anidados que bloquean algunos navegadores. Me gustaría poder acomodar el 99.9% de los documentos, pero rechazar aquellos que se anidan demasiado.
Dos preguntas estrechamente relacionadas:
- ¿Qué límites de profundidad de documentos están integrados en los navegadores? Por ejemplo, el navegador X no puede analizar o no compila documentos con profundidad> algún límite.
- ¿Las estadísticas detalladas de documentos están disponibles en la web? ¿Hay un sitio con estadísticas web que explique que algún porcentaje de documentos reales en la web tiene una profundidad de documento inferior a algún valor?
La profundidad del documento se define como 1 + el número máximo de recorridos principales necesarios para alcanzar la raíz del documento desde cualquier nodo en un documento. Por ejemplo, en
<html> <!-- 1 -->
<body> <!-- 2 -->
<div> <!-- 3 -->
<table> <!-- 4 -->
<tbody> <!-- 5 -->
<tr> <!-- 6 -->
<td> <!-- 7 -->
Foo <!-- 8 -->
la profundidad máxima es 8 ya que el nodo de texto "Foo" tiene 8 ancestros. El antepasado aquí se interpreta de forma no estricta, es decir, cada nodo es su propio antepasado y su propio descendiente.
Opera tiene algunas estadísticas de anidamiento de tablas, lo que sugiere que el 99,99% de los documentos tienen una profundidad de anidamiento de tablas inferior a 22, pero que los datos no contienen toda la profundidad del documento.
EDITAR:
Si la gente desea criticar la biblioteca de sanitización HTML en lugar de responder esta pregunta, por favor, hágalo. http://code.google.com/p/owasp-java-html-sanitizer/wiki/AttackReviewGroundRules explica cómo encontrar el código, dónde encontrar un banco de pruebas que le permita probar ataques y cómo informar problemas.
EDITAR:
Le pregunté a Adam Barth, y él muy amablemente me indicó el código del webkit que maneja esto.
Webkit, al menos, hace cumplir este límite. Cuando se created un treebuilder , recibe un límite de árbol que es configurable:
m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document), maximumDOMTreeDepth**(document)))
y se prueba mediante la prueba de block-nesting-cap .
Para webkit, la profundidad máxima del documento es configurable, pero por defecto es 512
http://trac.webkit.org/browser/trunk/Source/WebCore/page/Settings.h#L408
static const unsigned defaultMaximumHTMLParserDOMTreeDepth = 512;
Puede valer la pena preguntar [email protected]. Su estudio de 2005 ( http://code.google.com/webstats/ ) no cubre su pregunta en particular. Sin embargo, tomaron muestras de más de mil millones de documentos y están interesados en escuchar sobre cualquier cosa que consideren que valga la pena examinar.
--[Actualizar]--
Aquí hay un script en bruto que escribí para probar los navegadores que tengo (poniendo el número de elementos para anidar en la cadena de consulta):
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();
Y aquí están mis conclusiones (pueden ser específicas para mi máquina, Win XP, 3Gb Ram):
- Chrome 9: 3218 elementos anidados se representarán, 3129 pestañas se bloquea. (Chrome 9 es antiguo, lo sé, el actualizador falla en mi LAN corporativa)
- Safari 5: 3477 se renderizará, 3478 el navegador se cerrará completamente.
- IE8: 1000000+ se procesará (si la memoria lo permite), aunque el rendimiento se degrada significativamente cuando se convierten en números altos de 4 cifras debido al burbujeo de eventos al desplazar / mover el mouse / etc. Cualquier cosa por encima de 10000 parece bloquearse, pero creo que solo está tomando mucho tiempo, por lo que es un DoS efectivo.
- Opera 11: Solo limitado por la memoria, por lo que puedo decir, es decir, mi script se queda sin memoria para 10000000. Sin embargo, para los documentos grandes que se procesan, no parece haber ninguna degradación del rendimiento como en IE.
- Firefox 3.6: ~ 1500000 se procesará, pero las pruebas por encima de este rango provocaron que el navegador se bloquee con Mozilla Crash Reporter o simplemente se bloquee, a veces un número que funcionaba fallaría una vez más, pero números más grandes ~ 1700000 bloquearían Firefox directamente desde un reinicio.
Más sobre Chrome:
Al cambiar el DIV a un SPAN, Chrome pudo anidar 9202 elementos antes de fallar. Entonces, no es el tamaño del HTML lo que explica (aunque los elementos SPAN pueden ser más ligeros).
Las celdas de la tabla 2077 anidadas ( <table><tr><td>
) funcionaron (6231 elementos), hasta que se desplazó hasta la celda 445, luego se bloqueó, por lo que no puede anidar 445 celdas de tabla (1335 elementos).
Las pruebas con archivos generados desde el script (en lugar de escribir en nuevas ventanas) ofrecen tolerancias ligeramente más altas, pero Chrome aún falla.
Puede anidar los elementos de la lista 1409 ( <ul><li>
) antes de que se bloquee, lo cual es interesante porque:
- Firefox deja de sangrar los elementos de la lista después de 99, quizás una restricción programática.
- Opera''s sigue sangrando con fallas en 250, 376, 502, 628, 754, 880 ...
Establecer un DOCTYPE es efectivo en IE8 (ponerlo en modo estándar, es decir, var outboundHtml = ''<!DOCTYPE html>'';
): No anidará 792 elementos de la lista (la pestaña se bloquea / cierra) o 1593 DIV. No hizo ninguna diferencia en IE8 si la prueba se generó desde el script o se cargó desde un archivo.
Por lo tanto, el límite de anidamiento de un navegador aparentemente depende del tipo de elementos HTML que el atacante está inyectando y del motor de diseño. Podría haber algún HTML considerablemente más pequeño que esto. Y tenemos un DoS de HTML simple para los usuarios de IE8, Chrome y Safari con una carga útil considerablemente pequeña.
Parece que si va a permitir que los usuarios publiquen HTML que se representa en una de sus páginas, vale la pena considerar un límite en los elementos anidados si hay un límite de tamaño generoso.