zoukankan      html  css  js  c++  java
  • 【转载】网络攻击技术(三)——Denial Of Service & 哈希相关 & PHP语言 & Java语言

    找到了这个系列的原始作者:

    http://www.cnblogs.com/rush/archive/2012/02/05/2339037.html

    最近网络安全成了一个焦点,除了国内明文密码的安全事件,还有一件事是影响比较大的——Hash Collision DoS(通过Hash碰撞进行的拒绝式服务攻击),
    有恶意的人会通过这个安全漏洞让你的服务器运行巨慢无比,那他们是通过什么手段让服务器巨慢无比呢?我们如何防范DoS攻击呢?本文将给出详细的介绍。

    这一篇跟Hash关系比较密切。

    首先,发生哈希冲突时,我们可以使用冲突解决方法解决冲突,而主要的哈希冲突解决方法如下:

    开放地址法:在原hash空间中找位置放。
    
    再哈希法
    
    链地址法:开启新的链表来存储新的内容。
    
    建立一个公共溢出区

    上面开放地址法和链地址法的区别,可以查看 http://blog.csdn.net/w_fenghui/article/details/2010387

    注意:

    .NET是使用第一种策略解决哈希冲突,它根据某种原则将碰撞数据定位到其他槽中。

    PHP是使用单链表存储碰撞的数据,因此实际上PHP哈希表的平均查找复杂度为O(L),其中L为桶链表的平均长度;而最坏复杂度为O(N),此时所有数据全部碰撞,哈希表退化成单链表。下图是PHP中正常哈希表和退化哈希表的示意图。

    现在主流编程语言都采用的哈希算法是DJB(DJBX33A),而.NET中的NameValueCollection.GetHashCode()方法就是使用DJB算法。
    
    DJB的算法实现核心是通过给哈希值(Key)乘以33(即左移5位再加上哈希值)计算哈希值,接下来让我们看一下DJB算法的实现吧!

        uint hash = 5381;
        for (int i = 0; i < value.Length; i++)
        {
            // The value of ((hash << 5) + hash) the same as 
            // the value of hash * 33.
            hash = ((hash << 5) + hash) + value[i];
        }
     

    针对哈希的攻击:

    通过前面介绍.NET中GetHashCode()方法,现在我们对于其中的实现算法有了初步的了解,
    由于哈希冲突的原理就是针对具体的哈希算法来构造数据,使得所有数据都发生碰撞。

    这里我们使用了一个简单方法构造冲突数据——蛮力法。(效率低)

    由于蛮力法效率低,所以我们采用更加高效的方法中途相遇攻击(meet-in-the-middle attack)或等效子串(equivalent substrings)来构造冲突数据。

    等效子串:

    当两个字符串的哈希值发生冲突,例如:hash(“string1”)=hash(“string2”),那么由这两个子串在同一位置上构成的字符串也发生哈希冲突,
    
    假设“EZ”和“FY”在哈希函数中发生冲突,那么字符串“EzEz”,“EzFY”,“FYEz”,“FYFY”两两之间也发生冲突。
    
    示例:
    http://koto.github.io/blog-kotowicz-net-examples/hashcollision/kill.html

    中途相遇攻击:

    分成前后两节,先指定前面,和最终hash,然后构造后面的。
    
    其实没怎么看懂。文中有。

    总结:

    发post请求时候,发出大量重复hash的post参数,来让对方的hash算法总是冲突,然后崩溃。
    
    以上是我的理解。

    关于hash碰撞为什么能够产生DoS攻击,可以结合下面这篇来看:

    http://blog.jobbole.com/11516/

    哈希表是一种查找效率极高的数据结构,很多语言都在内部实现了哈希表。PHP中的哈希表是一种极为重要的数据结构,不但用于表示Array数据类型,
    还在Zend虚拟机内部用于存储上下文环境信息(执行上下文的变量及函数均使用哈希表结构存储)。 PHP哈希表最小容量是8(
    2^3),最大容量是0×80000000(2^31),并向2的整数次幂圆整(即长度会自动扩展为2的整数次幂,如13个元素的哈希表长度为16;
    100个元素的哈希表长度为128)。nTableMask被初始化为哈希表长度(圆整后)减1。 HashTable中的nTableMask是一个掩码,一般被设为nTableSize –
    1,与哈希算法有密切关系,后面讨论哈希算法时会详述。


    Zend HashTable的哈希算法异常简单:hashKey = key & nTableMask; 如果key是字符串,就先用time33算法,变成整型,然后处理。(time33算法前面也介绍了)

    基本攻击

    上文提到Zend HashTable的长度nTableSize会被圆整为2的整数次幂,假设我们构造一个2^16的哈希表,
    则nTableSize的二进制表示为:1 0000 0000 0000 0000,而nTableMask = nTableSize – 1为:0 1111 1111 1111 1111。
    接下来,可以以0为初始值,以2^16为步长,制造足够多的数据,可以得到如下推测: 0000 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0 0001 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0 0010 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0 0011 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0 0100 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0
    概况来说只要保证后16位均为0,则与掩码位于后得到的哈希值全部碰撞在位置0。

    攻击代码示例:

    <?php
     
    $size = pow(2, 16);
     
    $startTime = microtime(true);
     
    $array = array();
    for ($key = 0, $maxKey = ($size - 1) * $size; $key <= $maxKey; $key += $size) {
        $array[$key] = 0;
    }
     
    $endTime = microtime(true);
     
    echo $endTime - $startTime, ' seconds', "
    ";

    作者说用了近88秒才完成,并且在此期间CPU资源几乎被用尽。

    而正常的hash插入,如下,仅仅需要0.036秒。

    <?php
     
    $size = pow(2, 16);
     
    $startTime = microtime(true);
     
    $array = array();
    for ($key = 0, $maxKey = ($size - 1) * $size; $key <= $size; $key += 1) {
        $array[$key] = 0;
    }
     
    $endTime = microtime(true);
     
    echo $endTime - $startTime, ' seconds', "
    ";

    POST攻击

    一般情况下很难遇到攻击者可以直接修改PHP代码的情况,但是攻击者仍可以通过一些方法间接构造哈希表来进行攻击。例如PHP会将接收到的HTTP POST请求中的数据构造为$_POST,而这是一个Array,内部就是通过Zend HashTable表示,因此攻击者只要构造一个含有大量碰撞key的post请求,就可以达到攻击的目的。具体做法不再演示。 

    防御方法

    目前PHP的防护措施是控制POST数据的数量。在>=PHP5.3.9的版本中增加了一个配置项max_input_vars,用于标识一次http请求最大接收的参数个数,默认为1000。

    另外的防护方法是在Web服务器层面进行处理,例如限制http请求body的大小和参数的数量等,这个是现在用的最多的临时处理方案。具体做法与不同Web服务器相关,不再详述。

    上面的防护方法只是限制POST数据的数量,而不能彻底解决这个问题。例如,如果某个POST字段是一个json数据类型,会被PHPjson_decode,那么只要构造一个超大的json攻击数据照样可以达到攻击目的。

    理论上,只要PHP代码中某处构造Array的数据依赖于外部输入,则都可能造成这个问题,因此彻底的解决方案要从Zend底层HashTable的实现动手。

    一般来说有两种方式,一是限制每个桶链表的最长长度;二是使用其它数据结构如红黑树取代链表组织碰撞哈希(并不解决哈希碰撞,只是减轻攻击影响,
    将N个数据的操作时间从O(N^2)降至O(NlogN),代价是普通情况下接近O(1)的操作均变为O(logN))。

    目前使用最多的仍然是POST数据攻击,因此建议生产环境的PHP均进行升级或打补丁。至于从数据结构层面修复这个问题,目前还没有任何方面的消息。

    其他各种语言针对此类哈希碰撞攻击有漏洞的情况:

    除了Perl之外,这个漏洞使得包括Java, JRuby, PHP, Python在内的以下各种开发语言和许多常用软件都纷纷中招:
    Java, 所有版本
    JRuby <= 1.6.5 (目前fix在 1.6.5.1)
    PHP <= 5.3.8, <= 5.4.0RC3 (目前fix在 5.3.9,  5.4.0RC4)
    Python, all versions
    Rubinius, all versions
    Ruby <= 1.8.7-p356 (目前fix在 1.8.7-p357, 1.9.x)
    Apache Geronimo, 所有版本
    Apache Tomcat <= 5.5.34, <= 6.0.34, <= 7.0.22 (目前fix在 5.5.35,  6.0.35,  7.0.23)
    Oracle Glassfish <= 3.1.1 (目前fix在mainline)
    Jetty, 所有版本
    Plone, 所有版本
    Rack <= 1.3.5, <= 1.2.4, <= 1.1.2 (目前fix 在 1.4.0, 1.3.6, 1.2.5, 1.1.3)
    V8 JavaScript Engine, 所有版本
    ASP.NET 没有打MS11-100补丁

    Java相关

    这些语言使用的Hash算法都是非随机的比如JavaOracle使用的Hash函数: 

    static int hash(inth)

    {

    h ^= (h >>> 20) ^ (h >>> 12);

    return h ^ (h >>> 7) ^ (h >>> 4);

    }

    所谓非随机的” Hash算法,就可以猜。比如:

     

    1)在Java里, Aa和BB这两个字符串的hash code(或hash key) 是一样的,也就是Collision 。
    2)于是,可以通过这两个种子生成更多的拥有同一个hash key的字符串。如:”AaAa”, “AaBB”, “BBAa”, “BBBB”。这是第一次迭代。
    其实就是一个排列组合,写个程序就搞定了。
    3)然后,可以用这4个长度的字符串,构造8个长度的字符串。 在攻击时,只需要把这些数据做成一个HTTP POST 表单,然后写一个无限循环的程序,不停地提交这个表单。用浏览器就可以实现。
    当然,如果做得更精妙一点的话,把这个表单做成一个跨站脚本,然后找一些网站的跨站漏洞,放上去,于是能过SNS的力量就可以找到N多个用户从不同的IP来攻击某服务器。

     

    要防守这样的攻击,有下面几招:

    打补丁,把hash算法改了。

    限制POST的参数个数,限制POST的请求长度。

    最好还有防火墙检测异常的请求。

     

    Nodejs也有类似问题:

    使用 connect.limit 限制 request-body-size,直接上 connect.limit 模块解决。

    防范 http header 攻击

    请求的 http header 也会导致hash冲突,在V8层面未修复hash算法之前,可以通过简单的 http_patch.js 修复此问题

    if (this.__headerCount__ >= 100) {
        return;
    }

    也有业内人士说:

    目前暂无完美的解决方法。

     

     

     

  • 相关阅读:
    git 每次push和pull都需要提交密码
    git push时报错refusing to merge unrelated histories
    打包时,node内存溢出问题解决方法
    dva中roadhog版本升级后带来的问题及解决方法
    Android
    Python Model : glob 文件路径查找
    Tools info
    Python class
    Life Info
    Char 10 格式化及如何正确使用
  • 原文地址:https://www.cnblogs.com/charlesblc/p/5990475.html
Copyright © 2011-2022 走看看