Java 非随机散列函数导致的应用程序漏洞

Java 非随机散列函数导致的应用程序漏洞,java,security,ddos,Java,Security,Ddos,下面摘录自一篇文章,解释了由于哈希数据结构中使用的非随机哈希函数而导致拒绝服务(DoS)攻击的可能性 […]可以利用底层哈希算法中可预测的冲突来利用该条件 为了验证这一点,我查阅了Oracle Java HashMap的参考实现,并确实发现使用了一个静态哈希函数: static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>>

下面摘录自一篇文章,解释了由于哈希数据结构中使用的非随机哈希函数而导致拒绝服务(DoS)攻击的可能性

[…]可以利用底层哈希算法中可预测的冲突来利用该条件

为了验证这一点,我查阅了Oracle Java HashMap的参考实现,并确实发现使用了一个静态哈希函数:

    static int hash(int h) {
       h ^= (h >>> 20) ^ (h >>> 12);
       return h ^ (h >>> 7) ^ (h >>> 4);
    }
关于这个话题的另一个例子是:

Tomcat6.0.32服务器在大约10分钟内解析2MB的冲突密钥字符串 44分钟的i7 CPU时间,因此大约6 kbit/s的攻击者可以持续保留一个i7内核 忙碌的。如果攻击者有千兆连接,他可以让大约100.000个i7内核保持忙碌


我们如何防范这种脆弱性。此外,我们使用的许多软件都是开源的(Tomcat等),依赖于此实现。

受影响的Tomcat版本是Apache Tomcat=7.0.23作为固定版本。

最简单的解决方案是升级到Tomcat的固定版本。然而,我怀疑你想知道tomcat人需要改变的细节

这种攻击的工作原理是利用散列数据结构的一个常见实现细节——使用链表保存散列相同的所有值。由于列表的大小越来越大,向该链接列表添加值的效率很低。攻击者可以创建已知会生成冲突哈希的值列表,从而强制执行这种低效行为。为了防止出现这种情况,您有以下几种选择:

  • 防止冲突-通过在哈希函数中包含一些(伪)随机因子,防止攻击者生成冲突值。Perl已经做了很长时间了

  • 在你的存储桶中使用链表之外的东西-攻击有效,因为在链表中插入N个项目会增加N^2。如果在插入时使用平衡树或其他具有N logN增长的结构,则问题应该得到缓解。这可能会牺牲一些最佳/平均情况性能,以限制最坏情况的严重程度

  • 理解攻击向量 哈希映射的工作原理 假设博客上的评论表单接受参数–名字、姓氏、评论–作为帖子参数。在内部,Tomcat将这些参数存储为HashMap

    此HashMap的逻辑结构如下所示-

    
    "first_name" --> "Sripathi"
    "last_name" --> "Krishnan"
    "comment" ---> "DoS using poor Hashes"
    
    但是物理结构不同。首先将键转换为哈希代码,然后将哈希代码转换为数组索引

    因此,理想的物理结构成为——

    
    0 --> "Sripathi"
    1 --> "Krishnan"
    2 --> "DoS using poor Hashes"
    
    但可能的钥匙是无限的。因此,在某个时刻,两个键将具有相同的哈希代码。这将成为散列冲突

    碰撞时,物理结构变为:

    
    0 --> "Sripathi", "Krishnan"
    1 --> Empty
    2 --> "DoS using poor hashes"
    
    哈希冲突及其对性能的影响 当您有散列冲突时,插入一个新条目意味着按顺序迭代单个散列“bucket”中的所有元素,以确定它是否已经存在于映射中。如果所有元素都散列为相同的值,则插入一个元素的复杂性接近O(n)。在这种最坏的情况下插入n个元素会使它变得O(n*n)复杂

    简而言之:如果插入数千个具有相同哈希代码的密钥,服务器将需要大量CPU周期

    如何使用相同的哈希生成密钥? 在Java中,“Aa”和“BB”具有相同的哈希代码

    由于名为“等效子字符串”的属性,我们可以使用相同的哈希代码生成其他几个字符串,只需从这两个字符串开始

    第一次迭代:“AAAA”、“AABb”、“BbAA”、“bbbbbb”具有相同的哈希代码

    现在,我们有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=&bbbbbb=
  • 提交表格
  • 在一个循环中重复,并创建几个线程,以使所有服务器资源都用完
  • 由于这只是一个POST请求,攻击者还可以使用无辜的浏览器攻击服务器。只要找到一个存在跨站点脚本漏洞的网站,嵌入代码以发出POST请求,然后使用社会工程将链接传播到尽可能多的用户

    预防 一般来说,底层平台无法解决此问题。这被认为是一个应用程序框架问题。换句话说,Tomcat必须解决这个问题,而不是Oracle/Sun

    可能的修复措施包括:

  • 限制POST参数的数量-Tomcat 6.0.35+有一个新参数maxParameterCount。默认值为10000。越低越好,只要它不破坏您的功能

  • 限制POST请求的大小-要使攻击有效,有效负载必须很大。Tomcat允许的默认POST是2MB。将其减少到200KB将降低此攻击的有效性。tomcat中的参数是maxPostSize

  • Web应用程序防火墙-如果您有Web应用程序防火墙,您可以将其配置为阻止看起来可疑的请求。这是一个被动的措施,但如果您不能使用上述解决方案之一,那么最好使用它


  • 仅供参考-Tomcat的文档在这里-

    当填充的条目达到阈值时,Java HashMap/HashTable可以执行“调整大小”操作。很难说有一个固定的bucket HashMap在等着你。因为
    #!/usr/bin/python
    import sys
    alphabet = ["Aa","BB"]
    
    def func(str, length):
                    global alphabet
                    if(length != 0):
                                    for x in alphabet:
                                                    new_str = str+x
                                                    func(new_str, length-1)
                    else:
                                    sys.stdout.write(str+"=&")
    
    
    for x in range(1,16):
            func("",x)