hash hashcode变化_Web安全 | 没想到 Hash 冲突还能这么玩,你的服务中招了吗?

f820b827992d43d7e741ce3e5e05526c.png

图 by: 石头

背景

其实这个问题我之前也看到过,刚好在前几天,洪教授在某个群里分享的一个《一些有意思的攻击手段.pdf》,我觉得这个话题应该还是有不少人不清楚的,今天我就准备来“实战”一把,还请各位看官轻拍。

洪强宁(洪教授),爱因互动创始人兼 CTO,曾任豆瓣首席架构师,为中国 Python 用户组(CPUG)的创立者之一。
989b10f37e616ceca52ee0b6e1b1159a.png

这才是真大佬,原来洪教授在宜信的时候,就有分享过这个内容,可惜当初不知道没参加。看了之后才知道原来我上一篇的文章中讲的 计时攻击(Timing Attack) 也是其中的内容之一。哈哈,后面有空再研究研究继续讲其他内容。

Hash 冲突

啥叫 Hash 冲突?我们从 Hash 表(或者散列表)讲起,我们知道在一个 hash 表的查找一个元素,期望的时间复杂度为 O(1),怎么做到的呢?其实就是 hash() 函数在起作用。

初略来讲,hash 表内部实际存储还是跟数组类似,用连续的内存空间存储元素,只要通过某种方法将将要存储的元素映射为数组的下标,即可像数组一样通过下标去读取对应的元素,这也是为什么能做到 O(1) 的原因。

8658b5a8681242370c1399c1ab370cb9.png
Hash 示例

以上图为例,假设是我设计的一个 hash 函数,恰好满足如下条件:

  • hash("hello")=0:字符串 "hello" 就存储数组下标为 0 的地方;
  • hash("world")=2:"world" 存储数组下标为 2 的地方;
  • hash("tangleithu")=5:"tangleithu" 存储数组下标为 5 的地方;
0f4067fe5c9782a5d3a6b25cc98a0dce.png

目前来看一切好像很完美,但这终归是假设,我不能假设这个 hash 都很完美的将不同的字符串都映射到了不同的下标处。

另外来了个字符串,hash("石头") = 2,怎么办?这就是所谓的 “Hash 冲突”,最常见 Hash 冲突的解决方案其实就是“开链”法,其实还有比如线性试探、平方试探等等。

类似讲解 HashMap 的文章满大街都是,一搜一大把,本文就不详述了。为了方便读者理解,就简单来个例子。

724b7628b378b7f0dfef13eb56b73b69.png
Hash冲突开链法

开链法如上图所示,我们存储元素的时候,存储形式为一个链表,当冲突的时候,就在链表末尾直接添加冲突的元素。上图示例恰好运气比较差,字符串 shitoustone 算出来的下标都为 2。

这样一来,问题大了。原本我们期望 O(1) 的时间复杂度查找元素,现在变成在链表中线性查找了,而如果这个时候插入 个数据,最坏的情况下的时间复杂度就是 了。(这里就不讨论链表转树的情形)

ec31ba6d46f366df617b3a3745c4cf34.png
坏人可乘机而入

这就又给坏人留下了想象空间。只要坏人精心设计一组要放进 hash 表的字符串,且让这些字符串的 hashcode 都一样,这就会导致 hash 冲突,结果会导致 cpu 要花费大量的时间来处理 hash 冲突,造成 DoS(Denial of Service)攻击。

而用 hash 表存储的情形太常见了。在 Web 服务中,一般表单的处理都是用 hash 表来保存的(后端往往要知道通过某个具体的参数 key 获取对应的参数 value)。

实战

本文石头哥将以 Java SpringBoot 为例,尝试进行一次攻击。

不过别以为这种 “Hash 冲突 DoS” 以为只有 Java 才有哦,什么 Python,Apache Tomcat/Jetty,PHP 之类都会有这个问题的。其实早在 2011 年年末的时候就被大量爆出了,有的框架陆陆续续有一些改进和修复。详细情况可以看这篇文章:oCERT-2011-003 multiple implementations denial-of-service via hash algorithm collision[1]

这里,咱们给列举其中一个 Apatch Tomcat,来自 CVE-2011-4858[2]

Apache Tomcat before 5.5.35, 6.x before 6.0.35, and 7.x before 7.0.23 computes hash values for form parameters without restricting the ability to trigger hash collisions predictably, which allows remote attackers to cause a denial of service (CPU consumption) by sending many crafted parameters.

下面截图来自洪教授的 PPT,但内容的具体来源不详了(尝试找了下,没找到),大家参考参考就好。

79580828a805fddc83d73f783ea93b7e.png
实现 hash 冲突 DoS 攻击所须带宽

左边表示用不同的语言(框架)实现这种攻击所需要的带宽,右边是攻击的 cpu 目标。可以看出,实施这种攻击成本其实挺低的(后文石头的试验也佐证了这一点)。

c4fae040063acaa80fc480300424a365.png
不得不说 “PHP 是世界上最好的编程语言”(大家别打架),还是有一定道理的,哈哈哈哈哈哈 ?(一张图还不够,再加一张)
2323e1caa6ad3baad32f4e02c94fb741.png

上面的语言排序,不一定对,大家参考一下即可,不用纠结具体的准确性。

其实要验证,方法当然也相对简单,只要找出产生冲突的不同字符串即可,具体语言可能不一样。

talk is cheap

现在跟着我来尝试进行一次攻击吧,本人用自己的笔记本进行试验(配置:MBP 13-inch,2.5 GHz Intel Core i7,16 GB 2133 MHz LPDDR3)。

首先构造一把 hash 冲突的字符串,下面代码是 hash 冲突的字符串对的实例,后面的其实可以通过前面排列组合生成。

System.out.println("Aa".hashCode());
System.out.println("BB".hashCode());
System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBAaBBBBAa".hashCode());
System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBAaBBBBBB".hashCode());
// 输出
2112
2112
2067858432
2067858432

具体生成过程本文不详述了,感兴趣可以看看 StackOverflow 上的这篇文章 Application vulnerability due to Non Random Hash Functions[3],或者参考耗子叔的这篇 Hash Collision DoS 问题[4]

然后我启用一个 SpringBoot(2.2.2.RELEASE) 的 Web 服务,JDK 1.8(其实用 1.7 效果更明显)。

@RequestMapping("/hash")
public String hash(HttpServletRequest request) {
    // Demo,简单返回参数大小和其对应hashCode
    int size = request.getParameterMap().size();
    String key = (String)(request.getParameterMap().keySet().toArray())[0];
    return String.format("size=%s, hashCode=%s", size, key.hashCode());
}

先试水一把(如下图),看看基本功能正常,用 curl 发送请求即可,然后将 post 的字段放在文件里面(太长也只能放文件中)。

fdd29d0a8b9fddd8d6c7ab061cf37520.png
curl 实验结果

生成的字符串不够的话,还可以增加并发请求,可以借用类似 “Apache Benchmarking” 压测的工具发送请求,我之前也有一篇文章介绍了这个命令 性能测试工具 - ab 简单应用,感兴趣的可以参考一下。

6cbe8d4dae061c4d611fd6000f6e25bc.png
冲突的 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.

f3017b9b89ef274bbf6fdf6c8f27ecf6.png
post参数数量被限制

一种方法当然是去修改这个请求参数个数的限制。另外其实可以尝试用 JDK 1.7 去验证,应该效果会更好(原因,聪明的读者你肯定知道吧?)。这里石头哥就懒得去折腾了,直接尝试以量来取胜,用前文说的 ab 进行并发提交请求,然后观察效果。

这是我用如下参数跑的压测结果:

ab -c 200 -n 100000 -p req.txt 'localhost:8080/hash'

压测的结果如图所示:

5e5179e6c4e63bb41e5798519a29d5c1.png
ab 压测 hash 冲突结果

然后我们来看看 CPU 的变化情况,特意录屏做了个动图,可以看出还是相对比较明显的。从基本不占用 cpu 到 39.6%,然后突然就涨到 158% 了。

e2a0d39b65cdb5f29ef72940272b8ac2.gif
hash-collision-demo动图

实际试验中这个过程没有一直持续(上面是重试过程中抓到的其中一次),一方面因为本人用的 JDK 1.8,本来冲突后的查找过程已经优化了,可能效果并不明显,另外也猜测可能会有一些 cache 之类的优化吧,另外对于 10000 的量也还不够?具体我也没有深究了,感兴趣的读者可以去尝试一下玩玩。

到这里实验算成功了吧。

4090ae5e505ebbab2d6fcd979394b56f.png
实验成功就是拽

我这还是单机,要是多搞几个 client,不分分钟把 Web 服务搞死啊。

防御方法

上面实验算是成功了,那么防御方法呢?其实就是:

  • 改 hash 算法算一种了;例如像有的用随机算法作为 hash 函数的情况,可以用不同的随机种子尝试生成;但事实上并没有完美的 hash 算法的。
  • 本文实验中的也遇到这个了,就是要限制请求的参数个数,以及请求长度。在不影响业务的情况下,限制尽可能更小;
  • 上 WAF(Web Application Firewall),用专业的防火墙清洗流量。

最后

本文只供学习交流使用,请大家不要轻易尝试线上服务,不要轻易尝试线上服务,不要轻易尝试线上服务。

本人才疏学浅,如果有不对的地方,还望大家指出。

原创真心不易,希望你能帮我个小忙,如果本文内容你觉得有所启发和收获,不要白piao,请帮忙点个“在看”(你至少应该来个点赞吧f9de4f2409e6057ffca2a331bad6ee16.png),或者转发分享就更好啦,这将是我持续输出更多优质文章的最强动力。be595cce9a64789759e837f1014f5b32.png 

参考资料

[1]

oCERT-2011-003 multiple implementations denial-of-service via hash algorithm collision: http://ocert.org/advisories/ocert-2011-003.html

[2]

CVE-2011-4858: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4858

[3]

Application vulnerability due to Non Random Hash Functions: https://stackoverflow.com/questions/8669946/application-vulnerability-due-to-non-random-hash-functions

[4]

Hash Collision DoS 问题: https://coolshell.cn/articles/6424.html

往期推荐

美团Java线程池使用分析与实战

【干货】写给大忙人看的进程和线程

【秒杀系统】零基础上手秒杀系统(三):抢购接口隐藏 + 单用户限制频率

【算法】位运算与经典八皇后问题

【爱上面试官】系列:数据库索引

3d8916274f87afdcc523e6f1a3d996b9.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/502157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c#养老院老人信息管理系统源码 论文_包河区【失智老人养老院】

包河区【失智老人养老院】,光明老年护理院广受好评,本着“为政府分忧、帮子女尽孝”的服务宗旨;以“你把老人托给我,我把放心送给你”的服务理念;针对社会上有病的、子女无暇照顾的老年人,提供“爱心、耐心、热心”等全方位关怀服…

querywrapper 时间区间查询_雅思官方:关于增设用于英国签证及移民的雅思考试考点的通知!附20192020雅思考试时间安排...

接英国文化教育协会通知,为满足广大考生日益增长的报考需求,英国文化教育协会(雅思考试主办方)即日宣布,在南京财经大学(仙林校区)增设用于英国签证及移民的雅思考试考点,首场考试日期为2019年12月21日。考点具体信息如下&#xf…

scandall pro找不到扫描仪_吉林机箱风扇灯条找哪家

吉林机箱风扇灯条找哪家,阶新科技,合作理念--开诚布公,互相信任,团结奋斗。吉林机箱风扇灯条找哪家, 拆开机箱的前置面板可以看到前置面板中间带有长条形的叉戟灯条设计,这样也就导致前置的机箱风扇只能装在…

PHP8编译swoole出错,swoole自定义错误的方法

创建错误处理器实现ErrorHandlerInterface接口namespace App;use Core\AbstractInterface\ErrorHandlerInterface;class Test implements ErrorHandlerInterface{function handler( $msg,$file null,$line null,$errorCode null,$trace ){echo "文件{$file}的第{$line}…

大数据技术架构_架构大数据图

大数据管理数据处理过程图大数据(big data),指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察力。大数据处理的主要流程包括数据收集、数据存储、数据处理、数据应用等主要环节。随着业务的增长,大量和流程、规…

excel公式编辑器_Excel中自动更新超链接的文件目录,超简单

日常工作中,一个项目的文件往往会有很多个,在Excel中制作一个项目文件目录,可以快速方便的查看不同的文件。如下图所示,就是一个模拟的项目文件夹内的所有子文件夹,每个子文件夹内包含不同类型的文档,而且文…

蓝牙最新版本6.0_FIIL新品 T1 Lite,蓝牙5.2加持下的TWS耳机

说起汪峰老师,大家第一时间会想到他是国内内地著名男歌手、音乐创作人,摇滚先锋等几个身份,或者会联想到他是妻子著名国际影星章子怡。但如果你对音响或者耳机等音乐产品有所了解的话,你还会知道汪峰老师还亲自创立了一个知名的耳…

标准正态分布_正态分布,正态分布如何变换为标准正态分布

正态分布(Normal distribution),又名高斯分布(Gaussian distribution)若随机变量X服从一个数学期望为μ、方差为σ^2的正态分布,记为N(μ,σ^2)。其概率密度函数为正态分布的期望值μ决定了其位…

WSL安装Oracle,折腾记录:WSL(Windows Subsystem for Linux,Windows上的Linux子系统)安装后的环境配置-Go语言中文社区...

WSL(Windows Subsystem for Linux,Windows上的Linux子系统)的安装比较简单,教程网上较多,此处略过。安装后须要进行一系列配置(如软件源配置、中文配置、图形化配置、开发环境配置)才能投入使用,以Ubuntu为例(其他Debian、Kali、O…

cad钣金展开插件_户外垃圾桶顶盖钣金拆分展开方法

今天给大家讲解一个户外垃圾箱顶盖的拆分展开方法如下图拆分零件如下对称的两个零件如下打开SolidWorks,新建草图如下点击拉伸凸台命令设置参数如下点击倒圆角命令设置参数选择下面蓝色面绘制草图点击草图等距实体选择下图所示蓝色面向内偏移一个板厚1.5点击直线将下…

未能初始化appscan应用程序现在将关闭_企业区块链应用程序的两个关键问题

点击上方“蓝色字体”,选择 “设为星标”关键讯息,D1时间送达!很多架构师在使用区块链技术之前需要考虑一些关键问题,而这些问题与数据隐私和区块链类型有关。公共区块链通过提供数据的透明度、完整性、可追踪性、真实性来协调信任…

laravel 分词搜索匹配度_搜索引擎工作原理

抓取网页。每个独立的搜索引擎都有自己的网页抓取程序爬虫(Spider)。爬虫顺着网页中的超链接,从这个网站爬到另一个网站,通过超链接分析连续访问抓取更多网页。被抓取的网页被称之为网页快照。由于互联网中超链接的应用很普遍,理论上&#xf…

数据库表的软硬关联_Jimmy的关系型数据库设计心得 第一版

欢迎关注Jimmy的公众号:Jimmy嘚啵嘚,每周都有很多干货文章分享(最近比较懒,先保证每周写几篇,等忙完了再每日更新)最近在梳理以前设计关系型数据库的心得体会,或者斗胆说是方法论,梳…

83998 连接服务器出错_来申请一个阿里云服务器玩玩?

对开发有兴趣的小伙伴们可以去阿里云官网申请一个免费入门级的服务器小试身手。那么如何申请免费服务器呢?(这里吐槽不能超链接外部网页)进入官网这里我选择了左边的(体验时间长一点)选择Ubuntu 14.04 32位的系统(上面的地域选择可以百度一下自己的地理位置适合选择…

安卓项目打开有时候manifests不见了_手机通话音量太小?教你打开这个开关,再也不怕听不清了...

分享最实在的玩机技巧,洞察最前沿的科技资讯!大家好,这里是手机科技园!我们在生活中,经常用手机与家人朋友通话,可是有时候即使将音量开到最大,通话声音还是非常小,这到底是为什么呢…

为什么自己编写的页面总是在那里抖动_「内存抖动」?别再吓唬面试者们了行吗...

视频版本 本文在 B 站有对应的视频,如果你喜欢看视频版本,可以点 这里 去哔哩哔哩观看,或者点 这里 去 YouTube 观看。从「内存抖动」说起 面试官:你做过性能优化是吧。面试者:嗯是的,在卡顿和耗电问题上做…

vba 循环读取单元格_利用VBA打开顺序文件,并读取

大家好,疫情施虐,国外各地更有爆发的迹象,但无论怎样,我们一定要坚信,疫情终将会过去,曙光一定会到来。后疫情时代将会是一个全新的世界,很多理念都将被打破,大多数人不会再享受体制…

opcua客户端实现断线重连_虹科教您|实现OPC UA C/S快速部署及数据采集

想获取更多IIOT干货请点击蓝字,关注我们虹科HMI解决方案高性能高防护宽温★★★★★简介边缘HMI需要实现的主要功能包括连接到该边缘HMI的边缘设备的数据采集,实现边缘计算、提供人机接口、数据的本地存储与上传。在工业4.0的进程中,越来越多…

特征级融合_遥感影像融合的方法有哪些

遥感影像融合的方法有哪些 多种名称,常见的有 图像复合(Image Fusion) 影像融合(Image Merging)、 数据复合(Data Fusion)、 数据综合(Data Integration)、 影像综合(Image Integration)、 信息复合(Information Combination) 目的:把那些在空间和时间上…

最大值减最小值等于区间长度_呆哥数学每日一题 ——三角函数求余弦最小值...

如果想要获取往期每日一题电子版,可以加我微信:daigemath166,备注:知乎 每日一题呆哥解析:今天我们来看一道三角函数求余弦最小值的题目这里条件只有一个,那么我们第一步就是应该把两个角联系起来&#xff…