原文连接php
这是迄今为止第一个让我以为后怕的攻击方式,涉及的范围广难以防护,攻击效果立竿见影。大量的网站和Web接口都未作Hash碰撞攻击的防护,一拿一个准。java
随着RESTful风格的接口普及,程序员默认都会使用json做为数据传递的方式。json格式的数据冗余少,兼容性高,从提出到如今已被普遍的使用,能够说成为了Web的一种标准。不管咱们服务端使用什么语言,咱们拿到json格式的数据以后都须要作jsonDecode(),将json串转换为json对象,而对象默认会存储于Hash Table,而Hash Table很容易被碰撞攻击。我只要将攻击数据放在json中,服务端程序在作jsonDecode()时一定中招,中招后CPU会马上飙升至100%。16核的CPU,16个请求就能达到DoS的目的。git
全部测试程序都在Mac Pro下进行,为了测试方便我只构造了65536条json键值对,真正发起攻击时能够构造数十万甚至百万千万的数据。程序员
攻击数据我已经转换为json格式github
普通json数据json
一. JavaScript测试bash
//只须要一行代码就能看到效果 var jsonSrc = '这里输入json数据';
咱们只须要在js中输入一行代码就能看到效果,普通数据和Hash攻击数据都是65536行键值对。我本地测试的效果以下:
经过Chrome自带的任务管理器能够看出CPU立刻升到100%,将近1分钟才执行完成,而普通的数据几毫秒就能执行完成;服务器
二. PHP测试
$json = file_get_contents("https://raw.githubusercontent.com/laynefyc/php_thread_demo/master/hashNomal.json"); $startTime = microtime(true); $arr = json_decode($json,true); $endTime = microtime(true); echo "Nomal:".($endTime - $startTime)."\r\n"; $json = file_get_contents("https://raw.githubusercontent.com/laynefyc/php_thread_demo/master/hash.json"); $startTime = microtime(true); $arr = json_decode($json,true); $endTime = microtime(true); echo "Attack:".($endTime - $startTime)."\r\n";
PHP中咱们经过file_get_contents远程去拿数据,运行对比一下时间,相差10多秒,php-fpm单进程占用CPU 100%。
三. Java测试
public String index(){ String jsonStr = ""; try { FileReader fr = new FileReader("t.log");//须要读取的文件路径 BufferedReader br = new BufferedReader(fr); jsonStr = br.readLine(); br.close(); fr.close(); //关闭文件流 }catch(IOException e) { System.out.println("指定文件不存在");//处理异常 } Map<String, Object> map = new HashMap<String, Object>(); map = JSONObject.fromObject(jsonStr); return "Hash Collision ~"; }
Java中咱们经过读文件的方式作测试,Java的Hash算法与PHP和JavaScript有略微的差异,可是大同小异,咱们一样构造了6万行简单的数据。Spring boot框架中浏览器发起一次访问,26秒以后才返回结果,期间CPU被打满。
四. 其余语言还在研究中……
HashTable是很通用的数据结构,数据结构与算法上专门有一节课来讲它,因此Hash Collision是广泛存在的,各语言在实现上只是散列算法和Table存储上有细微差异。
为了验证Java的Hash碰撞攻击也生效,我整个端午假期都在看Java HashTable相关的文章,通过努力最后仍是成功的生成了攻击数据。过程很是不简单,这也验证了一个思想--全部高个上的东西最后分解出来都是基础的数据结构知识。
几年前PHP的版本仍是5.2,咱们能够把全部的Hash Key都放在POST请求的Body中,好比:
https://www.test.com/create-account
Post Data: k1=0&k2=0&k3=0...k999998=0&k999999=0
服务端拿到数据后会将全部参数存储到Hash Table($_POST)中,经过这种方式能很方便的实现攻击。可是如今这种方式行不通了,由于咱们很容易就能在Nginx层和PHP层限制Http请求的参数个数和大小。PHP默认只容许1000个参数,这个量级对服务器彻底没影响。
如今是2017年,json格式和RESTful风格的接口已经很是流行。带给咱们便捷编码的同时,也给Hash Collision Dos提供了新的方式。如今不少RESTful风格的接口以下:
Data: {"action":"create-account","data":""}
如上接口,咱们直接把攻击的数据放入data参数中,服务端接收到数据后确定会作jsonDecode(),很方便的就达到了攻击的目的。
要想防护Hash Collision Dos攻击,行业内已经有不少成熟的方案了,不过都是建议换语言或者重写HashTable。这里只说当前json格式解析的问题。首先咱们须要增长权限验证,最大可能的在jsonDecode()以前把非法用户拒绝。其次在jsonDecode()以前作数据大小与参数白名单验证。旧项目的改造与维护成本若是很高,建议本身重写jsonDecode()方法。
写了这么多,其实最有乐趣的地方仍是如何生成攻击数据。以后我会详细的写这部分。最后,Golang和Python能躲过Hash Collision Dos测试吗?敬请期待