心脏滴血漏洞分析与复现
本文最后更新于:2024年7月30日 晚上
之前写了TLS的详解,这里拓展一下心脏滴血这个声名远播的老洞
心脏滴血漏洞(CVE-2014-0160)
一个出现在加密程序库OpenSSL的安全漏洞,该程序库广泛用于实现互联网的传输层安全(TLS)协议。
此问题的原因是在实现TLS的心跳扩展时没有对输入进行适当验证(缺少边界检查),因此漏洞的名称来源于“心跳”(heartbeat)。该程序错误属于缓冲区过滤,即可以读取的数据比应该允许读取的还多。
HeartBleed主要存在与OpenSSL的1.0.1版本到1.0.1f版本。
利用该漏洞,攻击者每次可以远程读取服务器内存中至多64K的数据,获取内存中的敏感信息。
心跳包
可以简单了解一下心跳包的作用,它是一种用于保持TLS连接活跃并检测连接状态的小型数据包。在TLS连接建立之后,定期发送心跳包以确保连接在长时间没有数据传输时不被中断。如果未收到预期的响应,表明连接可能已断开或出现问题。
那么心跳请求是如何工作的:
心跳扩展允许一个TLS对等体向另一个对等体发送一个心跳请求,接收方应以心跳响应形式回送相同的数据。具体流程如下:
- 心跳请求:一方发送包含随机数据和请求类型的心跳请求消息。
- 心跳响应:接收方在接收到心跳请求后,必须在心跳响应消息中返回相同的随机数据。
心跳消息的格式:
- 类型:心跳请求或心跳响应。
- Payload长度:负载数据的长度。
- Payload数据:实际的负载数据,可以是任意内容。
- Padding:可选的填充数据,确保消息长度符合特定要求。
原理分析
那么这个心脏滴血漏洞是如何形成的呢,其实很简单
在客户端发送完心跳包之后,服务端会短暂的存储心跳包中的内容,分配一个内存缓冲区(一个物理内存区域用以存储信息),该区域的存储空间和心跳请求信号里的长度一致。接下来,它会存储请求信号的加密数据到内存缓冲区,然后读取数据并将其发送回你的浏览器,来证明连接仍然存在。
关键是,OpenSSL官方编写的库函数里没有检查这个客户端心跳包的实际内容和它给定的长度,也就是说本身是一个10字节的数据,客户端声明了20字节的内容,服务端就会开辟20字节的空间,导致服务端返回了20字节的数据。
一句话:计算机接受心跳请求时从不检查该请求和它声称的内容是否一致,及从不检查所请求的数据长度是否和声称的数据长度一致,导致响应方返回额外长度的数据。
导致心脏出血漏洞的编程错误可以归于一行代码:
1 |
|
memcpy()是复制数据的命令。bp是被复制的数据的存储区域,pl是被复制的数据的来源,payload是被复制的数据长度。问题在于,该命令没有检验pl复制的数据是否和payload给予的长度相符。
所有原理其实非常简单,早期的开发存在极大的安全隐患。
复现
首先默认已经配置好了docker以及下载了vulhub,打开openssl/CVE-2014-0160,使用docker-compose up -d
拉取镜像,然后环境就搭建好了,攻击使用metasploit。
使用docker ps
查看一下容器的状态,发现TCP服务开启在8080和8443端口。当然实际攻击使用端口扫描工具可以探测出来,比如Nmap。
接着我们打开Kali,使用命令msfconsole
打开Metaspolit
搜索心脏滴血漏洞,然后use 1
然后设置IP和端口,run就可以实现信息泄露,
结束