Mik*_*uel 22 html metrics depth
我想允许嵌入HTML,但由于深度嵌套的HTML文档导致某些浏览器崩溃,因此避免使用DoS.我希望能够容纳99.9%的文档,但拒绝那些嵌套太深的文档.
两个密切相关的问题:
文档深度定义为1 +从文档中的任何节点到达文档根目录所需的最大父遍历数.例如,在
<html> <!-- 1 -->
<body> <!-- 2 -->
<div> <!-- 3 -->
<table> <!-- 4 -->
<tbody> <!-- 5 -->
<tr> <!-- 6 -->
<td> <!-- 7 -->
Foo <!-- 8 -->
Run Code Online (Sandbox Code Playgroud)
由于文本节点"Foo"具有8个祖先,因此最大深度为8.这里的祖先是非严格的解释,即永远的节点是它自己的祖先和它自己的后代.
Opera有一些表嵌套统计信息,这表明99.99%的文档的表嵌套深度小于22,但该数据不包含整个文档深度.
编辑:
如果人们想批评HTML清理库而不是回答这个问题,请这样做. http://code.google.com/p/owasp-java-html-sanitizer/wiki/AttackReviewGroundRules介绍了如何查找代码,在哪里找到可以尝试攻击的测试平台,以及如何报告问题.
编辑:
我问Adam Barth,他非常友好地指出了处理这个问题的webkit代码.
至少Webkit强制执行此限制.当TreeBuilder作为被创建它接收一棵树的限制,可以配置:
Run Code Online (Sandbox Code Playgroud)m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document), maximumDOMTreeDepth**(document)))
并通过块嵌套测试进行测试.
Lee*_*ski 19
可能值得询问coderesearch@google.com.他们2005年的研究(http://code.google.com/webstats/)并未涵盖您的具体问题.他们对10多亿份文件进行了抽样调查,并且有兴趣了解您认为值得研究的任何内容.
- [更新] -
这是我编写的用于测试我所拥有的浏览器的粗略脚本(将要嵌入到查询字符串中的元素数量):
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();
Run Code Online (Sandbox Code Playgroud)
以下是我的发现(可能是我的机器,Win XP,3Gb Ram特有的):
有关Chrome的更多信息
将DIV更改为SPAN会导致Chrome在崩溃之前能够嵌套9202个元素.因此,不是HTML的大小(尽管SPAN元素可能更轻量级).
嵌套2077表格单元格(<table><tr><td>)工作(6231个元素),直到您向下滚动到单元格445,然后它崩溃,因此您无法嵌套445个表格单元格(1335个元素).
使用从脚本生成的文件进行测试(而不是写入新窗口)可以提供稍高的容差,但Chrome仍然会崩溃.
你可以<ul><li>在崩溃之前嵌套1409个列表项(),这很有趣,因为:
设置DOCTYPE在IE8中有效(将其置于标准模式,即var outboundHtml = '<!DOCTYPE html>';):它不会嵌套792个列表项(选项卡崩溃/关闭)或1593个DIV.无论测试是从脚本生成还是从文件加载,IE8都没有区别.
因此浏览器的嵌套限制显然取决于攻击者注入的HTML元素的类型以及布局引擎.可能有一些HTML比这小得多.我们为IE8,Chrome和Safari用户提供了一个简单的HTML DoS,其负载相当小.
看来如果您要允许用户发布在您的某个页面上呈现的HTML,那么如果存在大小限制,则值得考虑嵌套元素的限制.