青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?( 三 )


青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?
本文插图
冲突的 hashcode 一样
打个断点看看效果 , 如上图所示 , 确实所有的 hash 值都是一样的 。 不过一次请求好像并没有影响我电脑 cpu 的明显变化 。
我测试的字符串已经是 29859 个了 , 正准备生成更多的冲突的字符串进行尝试时 , 结果仔细一看才发现请求被截断了 , 请求返回的参数 size 大小为 10000 。 原来 SpringBoot 内置的 tomcat 给做了手脚 , 看下图 , 因为默认的请求的参数个数大小被限制成 10000 了 。
More than the maximum number of request parameters (GET plus POST) for a single request ([10,000]) were detected. Any parameters beyond this limit have been ignored. To change this limit, set the maxParameterCount attribute on the Connector.
青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?
本文插图
post参数数量被限制
一种方法当然是去修改这个请求参数个数的限制 。 另外其实可以尝试用 JDK 1.7 去验证 , 应该效果会更好(原因 , 聪明的读者你肯定知道吧?) 。 这里石头哥就懒得去折腾了 , 直接尝试以量来取胜 , 用前文说的 ab 进行并发提交请求 , 然后观察效果 。
这是我用如下参数跑的压测结果:
ab -c 200 -n 100000 -p req.txt "localhost:8080/hash"
压测的结果如图所示:
青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?
本文插图
ab 压测 hash 冲突结果
然后我们来看看 CPU 的变化情况 , 特意录屏做了个动图 , 可以看出还是相对比较明显的 。 从基本不占用 cpu 到 39.6% , 然后突然就涨到 158% 了 。
青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?
本文插图
hash-collision-demo动图
实际试验中这个过程没有一直持续(上面是重试过程中抓到的其中一次) , 一方面因为本人用的 JDK 1.8 , 本来冲突后的查找过程已经优化了 , 可能效果并不明显 , 另外也猜测可能会有一些 cache 之类的优化吧 , 另外对于 10000 的量也还不够?具体我也没有深究了 , 感兴趣的读者可以去尝试一下玩玩 。
到这里实验算成功了吧 。
青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?
本文插图
实验成功就是拽
我这还是单机 , 要是多搞几个 client , 不分分钟把 Web 服务搞死啊 。
防御方法 上面实验算是成功了 , 那么防御方法呢?其实就是:

  • 改 hash 算法算一种了;例如像有的用随机算法作为 hash 函数的情况 , 可以用不同的随机种子尝试生成;但事实上并没有完美的 hash 算法的 。
  • 本文实验中的也遇到这个了 , 就是要限制请求的参数个数 , 以及请求长度 。 在不影响业务的情况下 , 限制尽可能更小;
  • 上 WAF(Web Application Firewall) , 用专业的防火墙清洗流量 。
最后 本文只供学习交流使用 , 请大家不要轻易尝试线上服务 , 不要轻易尝试线上服务 , 不要轻易尝试线上服务 。
本人才疏学浅 , 如果有不对的地方 , 还望大家指出 。
【青年没想到 Hash 冲突还能这么玩,你的服务中招了吗?】


推荐阅读