了解攻击向量
HashMap 的工作原理
假设博客上的评论表单接受参数——名字、姓氏、评论——作为帖子参数。在内部,Tomcat 将这些参数存储为 HashMap。
这个HashMap的逻辑结构是这样的——
"first_name" --> "Sripathi"
"last_name" --> "Krishnan"
"comment" ---> "DoS using poor Hashes"
但物理结构不同。首先将键转换为 hashCode,然后将 hashCode 转换为数组索引。
理想的物理结构因此变成——
0 --> "Sripathi"
1 --> "Krishnan"
2 --> "DoS using poor Hashes"
但是可能的键是无限的。所以在某些时候,两个键将具有相同的哈希码。这变成了哈希冲突。
随着碰撞,物理结构变为:
0 --> "Sripathi", "Krishnan"
1 --> Empty
2 --> "DoS using poor hashes"
哈希冲突和对性能的影响
当您有哈希冲突时,插入一个新条目意味着依次迭代单个哈希“桶”中的所有元素,只是为了找出它是否已经存在于映射中。如果所有元素散列到相同的值,则插入一个元素可能会接近 O(n) 复杂度。在这种最坏的情况下插入 n 个元素会使其复杂度为 O(n*n)。
简而言之:如果您插入数千个具有相同 hashCode 的键,服务器将需要大量 CPU 周期。
如何生成具有相同哈希的密钥?
在 Java 中,“Aa”和“BB”具有相同的哈希码。
由于一个名为“等效子字符串”的属性,我们可以生成其他几个具有相同哈希码的字符串,只需从这两个字符串开始。
第一次迭代:“AAAA”、“AABb”、“BbAA”、“BbBb”具有相同的哈希码
现在,我们有 4 个具有相同哈希码的字符串。我们可以对它们进行置换以生成 16 个具有相同哈希码的字符串。例如 :
"AaAaAaAa", "AaAaBBBB", "AaAaAaBB", "AaAaBBAa",
"BBBBAaAa", "BBBBBBBB", "BBBBAaBB", "BBBBBBAa",
"AaBBAaAa", "AaBBBBBB", "AaBBAaBB", "AaBBBBAa",
"BBAaAaAa", "BBAaBBBB", "BBAaAaBB", "BBAaBBAa",
所有这 16 个字符串都具有相同的哈希码。
您现在可以获取这 16 个字符串,并生成 256 个具有相同哈希码的字符串。
简而言之:生成一大组具有精确哈希码的字符串非常容易。
你如何攻击服务器?
- 创建数千个具有相同哈希码的字符串(见上文)
- 像这样构造一个 POST 请求 - AaAa=&AaBB=&BBAa=&BBBB= ....
- 提交表格
- 循环重复,并创建多个线程,使所有服务器资源都用完
因为这只是一个 POST 请求,攻击者也可以使用无辜的浏览器来攻击服务器。只需找到一个存在跨站脚本漏洞的网站,嵌入代码以发出 POST 请求,然后使用社交工程将链接传播给尽可能多的用户。
预防
一般来说,底层平台无法解决这个问题。这被认为是应用程序框架问题。换句话说,Tomcat 必须解决这个问题,而不是 Oracle/Sun。
可能的修复包括:
限制 POST 参数的数量- Tomcat 6.0.35+ 有一个新参数maxParameterCount。默认值为 10,000。越低越好,只要它不会破坏您的功能。
限制 POST 请求的大小- 为了使攻击起作用,有效负载必须很大。Tomcat 允许的默认 POST 为 2MB。将其减少到 200KB 将降低此攻击的有效性。tomcat中的参数是maxPostSize
Web 应用程序防火墙- 如果您有 Web 应用程序防火墙,您可以将其配置为阻止看起来可疑的请求。这是一种反应性措施,但如果您无法使用上述解决方案之一,则很好。
仅供参考 - Tomcat 的文档在这里 - http://tomcat.apache.org/tomcat-6.0-doc/config/http.html