概述
“心脏滴血漏洞”测评经验分享
1 前言
1.1 编写目的
经验分析贴,赚C币买文章;
1.2 读者对象
本文档读者对象为:测评相关工程师、项目管理者、测试工程师、质量管理人员、文档工程师等技术人员。
读者对象 | 阅读重点与建议 |
---|---|
测评工程师 | 建议阅读全部内容。 |
项目管理者 | 建议阅读软件介绍概要性文档。 |
质量管理人员 | 建议阅读介绍等概要性文档。 |
文档工程师 | 建议阅读介绍概要性文档。 |
1.3 名词术语
名词、术语 | 解 释 |
---|---|
缓冲区过读 | 缓冲区过读是一类程序错误,即程序从缓冲器读出数据时超出了边界,而读取了(或试图读取)相邻的内存。 |
OpenSSL | OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。 |
完全正向保密 | 完全正向保密(perfect forward secrecy)是信息安全中提出的观点。要求一个密钥只能访问由它所保护的数据;用来产生密钥的元素一次一换,不能再产生其他的密钥;一个密钥被破解,并不影响其他密钥的安全性。设计旨在长期使用密钥不能确保起安全性的情况下而不影响过去会话的保密性。 |
1.4 参考文档
编号 | 文档、资料名称 | 来源 | 备注 |
---|---|---|---|
1 | Rix Tox(知乎) | https://www.zhihu.com/question/23328658/answer/24236735 | 无 |
2 测评前的准备
2.1 心脏滴血漏洞是什么?
Heartbleed漏洞,也叫“心脏滴血漏洞”。是OpenSSL加密软件库中的一个严重漏洞。这个漏洞允许窃取正常情况下使用SSL/TLS加密保护的信息;
自2011年12月31日,漏洞就已经存在,而且随着OpenSSL版本1.0.1于2012年3月14日释出,有缺陷的代码被互联网广泛使用;Heartbleed漏洞允许互联网上的任何人不受限制的读取受OpenSSL漏洞保护系统的内存。攻击者可根据漏洞窃听信息,直接从服务和用户那里窃取潜在的敏感数据,甚至包括服务器的专用主密钥;
如果存在此漏洞;攻击者可以通过被动中间人攻击,获取此时服务器内存中存储的信息(如果服务器和客户端未使用完全正向保密,或使用了完全正向保密时攻击方发动“主动中间人攻击”)。攻击者无法控制服务器返回的数据,因为服务器会使用一个随机内存块(最大64KB)作为响应;而且攻击者可以不断发送攻击请求报文,获取服务器内存中的数据。
安全公司Codenomicon和Google工程师Neel Mehta最早于2014年4月8日发现(公布)了 OpenSSL的Heartbleed漏洞;安全公司Codenomicon为这个漏洞制作了一个符合漏洞形象的logo;Codenomicon公司的工程师“Ossi Herrala”为漏洞名起了很炫的名字:“Heartbleed”;心脏滴血的名称由此而来。
2.2 漏洞范围
Heartbleed于2011年12月被引入到OpenSSL中,自OpenSSL于2012年3月14日发布1.0.1以来就一直存在。2014年4月7日发布的OpenSSL 1.0.1g修复了这个漏洞。.
说明 | 存在漏洞的SSL/TLS相关版本 |
---|---|
存在漏洞的版本 | OpenSSL1.0.1、1.01a、1.01b、1.01c、1.01d、1.01e、1.01f、Beta 1 of OpenSSL1.02等版本 |
不存在漏洞的版本 | OpenSSL1.0.1g、OpenSLL1.0.0、OpenSSL 0.9.8、OpenSSL 1.0.2-beta2、和以上SLL高版本 |
漏洞详细说明见:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160
自2014年漏洞发布起即全球%30的网站存在被攻击的风险,漏洞影响的范围到底有多大? 根据以下当年发布的信息可以说明情况;
节选来自Heartbleed的官方说明:OpenSSL在Web容器如Apache/Nginx中使用,这两款中间件的全球份额超过66%。一些大型的互联网公司常使用 OpenSSL,而这曾经被认为是最安全的数据传输手段之一;
众多网络路由器厂商包括 Cisco Systems 与 Juniper Networks等,在漏洞公布当天纷纷发布了紧急公告,列出一系列受此漏洞影响的路由器产品。虽说这些产品由于使用旧版SSL,厂商也表示会尽快更新补洞,据悉,有的黑客在漏洞发布一年前就已经在利用这个漏洞了,获取到了不少大网站的敏感信息;
国内知名企业如淘宝、阿里、360、京东(滚动资讯)、微信、支付宝等公司的技术团队也在漏洞发布当天彻夜奋战,和黑客们开展起了一场“你盗我堵”的赛跑,在黑客窃取更多用户数据前赶紧予以修复…
下面图片反应了2014年在发布漏洞后的紧急情况:
2.3 漏洞描述
Heartbleed漏洞,这项严重缺陷(CVE-2014-0160)的产生是由于未能在memcpy()调用受害用户输入内容作为长度参数之前正确进行边界检查。攻击者可以追踪OpenSSL所分配的64KB缓存、将超出必要范围的字节信息复制到缓存当中再返回缓存内容,这样一来受害者的内存内容就会以每次(每次SSL心跳报文请求)64KB的速度进行泄露;原理如下图所示:
2.4 漏洞原理
2.4.1 心跳检测报文(Heartbeat)
要对心脏滴血漏洞进行更好的理解,首先需要知道心跳检测报文的作用和运行原理,这里做简要解释;
(A)心跳检测报文的作用
TLS心跳扩展报文为TLS/DTLS提供了一种允许在不重新进行商议和发送路径MTU探索包(PMTU)的情况下而使用保持持续通信功能的新协议。
所谓心跳检测,就是建立一个 Client Hello 问询来检测对方服务器是不是正常在线 ,服务器发回 Server hello,表明正常保持SSL通讯。就像我们打电话时会问对方“喂听得到吗?”一样;
每次问询都会附加一个问询的字符长度“pad length”,如果这个“pad length” 大于实际的长度,应答方仍是会返回相同字符长度的字符信息。
(B)TLS/DTLS心跳检测报文的结构
TLS数据包格式如下:
心跳包字段 | 长度 | 说明 |
---|---|---|
ContentType | 1byte | 心跳包类型,IANA组织把type编号定义为24(0x18) |
ProtocolVersion | 2bytes | TLS的版本号,目前主要包括含有心跳扩展的TLS版本:TLSv1.0,TLSv1.1,TLSv1.2 |
length | 2bytes | HeartbeatMessage的长度 |
HeartbeatMessageType | 1byte | Heartbeat类型 01表示heartbeat_request 02表示heartbeat_response |
payload_length | 2bytes | payload长度 |
payload | payload_length个bytes | payload的具体内容 |
padding | >=16bytes | padding填充,最少为16个字节 |
DTLS数据包格式如下:
心跳包字段 | 长度 | 说明 |
---|---|---|
pe | 1byte | 心跳包类型,IANA组织把type编号定义为24(0x18) |
ProtocolVersion | 2bytes | DTLS的版本号,DTLS1.0基于TLS1.1,DTLS1.2基于TLS1.2 |
epoch | 2bytes | 为一个计数器,每一个加密状态改变时加一。主要用来区分在一个多次重新协商的情况,多个记录包文可能会具有相同的序列号,因此再用这个域来区分,接收者可以用来区分不同的包。epoch初始值为0,每发送一个changeCipherSpec消息后加一 |
sequence_number | 6bytes | 记录层的序列号,在每一个ChangeCipherSpec消息发送之后,sequence_number都设置为0 |
length | 2bytes | HeartbeatMessage的长度 |
HeartbeatMessageType | 1byte | Heartbeat类型 01表示heartbeat_request 02表示heartbeat_response |
payload_length | 2bytes | payload长度 |
payload | payload_length个bytes | payload的具体内容 |
padding | >=16bytes | padding填充,最少为16个字节 |
(C)TLS/DTLS心跳检测报文抓包示范
心跳检测报文包括A、请求包(heartbeat Request)和B、响应包(heartbeat Response);本文以常见TLS数据包为例,通过wireshark进行抓包获取信息如下:
A、TLS请求包抓包示例如下:
B、TLS响应包抓包示例如下:
通过对比心跳检测请求报文和响应报文不难看出,响应报文和请求报文使用相同的报文格式;如果仔细观察请求报文,可以发现请求报文请求的报文长度是16384,但实际的载荷(Payload)值为0;但应答方回复请求方的实际载荷(Payload)为16381(约64KB);这里,就是心脏发生滴血的地方;即可以发现攻击方通过制造畸形心跳检测请求报文进行了攻击;
如果打开应答报文Payload字段,可以看到因漏洞产生内存溢出的数据;溢出的数据是随机的,但是攻击方可以通过多次进行攻击,从而获取更多应答方内存中的数据,直到获取有价值的数据;而且64KB是可以泄露出足够多的信息的;如下图攻击方通过伪造报文已经获取了关键的用户账户和口令信息:
这里还想说一些题外话,此类漏洞主要是因为攻击方制造了畸形报文进行了攻击,目前可以抵御的手段可以通过IPS、WAF等安全防护规则库进行拦截;但根本上最好的修复方法还是更新SSL/TLS版本;后续的SSL/TLS版本中对协议代码进行了优化(对输入内容作为长度参数之前正确的进行了边界检查)。
2.4.2 代码原理示例
漏洞出现在SSL服务ssl/d1_both.c中,对用户传入的payload长度没有检查就进行内存拷贝;下面是代码示意:
漏洞出现在SSL服务ssl/d1_both.c中,对用户传入的payload长度没有检查就进行内存拷贝;下面是代码示意:
1)基本结构
-------------------------------------------------------------------------
int
dtls1_process_heartbeat(SSL *s)
{
unsigned char *p = &s->s3->rrec.data[0], *pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
}
-------------------------------------------------------------------------
2)p指向一条SSLv3的记录,结构如下:
-------------------------------------------------------------------------
typedef struct ssl3_record_st
{
int type; /* type of record */
unsigned int length; /* How many bytes available */
unsigned int off; /* read/write offset into 'buf' */
unsigned char *data; /* pointer to the record data */
unsigned char *input; /* where the decode bytes are */
unsigned char *comp; /* only used with decompression - malloc()ed */
unsigned long epoch; /* epoch number, needed by DTLS1 */
unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */
} SSL3_RECORD;
-------------------------------------------------------------------------
3)回到上面的程序,接下来对指针进行一些操作:
-------------------------------------------------------------------------
/* Read type and payload length first */
hbtype = *p++;
n2s(p, payload);
pl = p;
-------------------------------------------------------------------------
4)这里先读取个type,然后n2s把下一个length的两个字节放到payload里面,作为后面内存拷贝的长度;
-------------------------------------------------------------------------
unsigned char *buffer, *bp;
int r;
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
/* ... */
/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);
-------------------------------------------------------------------------
注意这个payload长度是用户请求的,而在分配的时候完全没有对于实际的SSL记录长度进行审查,bp会直接返回给用户,所以攻击者可以dump出任意长度(最大为65535(payload)+1+2+16(padding)=64k)的数据,而pl也是用户传入的,只要把pl设置的很小,dump出来的数据就会包含更多别的敏感数据。具体的利用方法见exploit demo,就不详细分析了。
作者:Rix Tox
链接:https://www.zhihu.com/question/23328658/answer/24236735
来源:知乎
3 测评实施要点
通过上文对心脏滴血漏洞的理解,测评过程中无非是存在四个需要解决的问题;一是怎么发现,二是怎么测试,三是怎么写;四是怎么判定风险。本文不涉及渗透类测试,不提供漏洞POC测试工具下载。
3.1 发现漏洞的方法
(A)通过协议版本判断
如本文2.2章节漏洞范围中【=存在心脏滴血漏洞的SSL/TLS相关版本】所示,当前存在心在滴血漏洞的版本有OpenSSL1.0.1、1.01a、1.01b、1.01c、1.01d、1.01e、1.01f、Beta 1 of OpenSSL1.02等版本;如果当前所使用SSL技术包括以上版本,则可能存在漏洞。
3.2 测试漏洞的方法
(A)通过Wireshark抓包测试(包分析)
1)异常的SSL心跳检测请求报文会在Wireshark软件中自动标识出来,这里不得不说测评工具的重要性;如下图,Wireshark在发现异常报文后,将会用红色覆盖异常字段;再通过人工判断可以发现当前载荷和请求载荷内容明显存在问题;
2)找到应答报文,可以发现内存溢出的信息,其中包括了用户名和口令;
(B)通过Wireshark抓包测试(TCP追踪)
根据心跳检测报文原理我们知道心跳检测报文是用于保证单次会话的连通性;因此我们可以根据TCP流追踪取,可以获取到未通过TLS加密的部分(其实是内存溢出,和加密无关);如下图:
3.3 描述漏洞的方法
知道了怎么发现、测试的方法,描述方面即只要包括关键截图和发现的过程内容即可;重点是描述出当前使用的SSL/TLS协议版本;指出存在心脏滴血漏洞,然后将测试过程截图保存再结果记录表后面,相关描述见“结果记录表“编写规范,这里不多做概述。
3.4 判定风险的方法
依据公开的“信息系统密码应用高风险判定指引”;此类漏洞风险被归类到密码产品和密码服务,且属于高风险项;依据截图如下:
判定方面,因实际采用了密码技术,因此不能给不符合;在本文中,密码套件为TLS_EDCDHE_RSA_WITH_AES_256_CBC_SHA(0xc014);不考虑密钥管理方面,这里应该给部分符合;
即:部分符合,存在高风险(高风险判定指引第5.3章,hearbleed高风险漏洞)。
4 总结
以上是本次相关心脏滴血漏洞的分享内容,通过对漏洞的历史、重要性、原理、测试方法等进行了回顾,有助于我们对漏洞进行更好的理解,并根据漏洞情况编写结果记录;本文没有关于渗透类POC相关测试的内容,理论篇借鉴了CDSN和知乎上各类文章,比较重要的文章已标注内容来源;个人理解部分欢迎指出问题;
需要说明的是,虽然是2014年曝光的漏洞,但是目前依然可能有不少使用低版本的TLS/SSL协议的情况,因此此类漏洞,需要及时发现。
最后
以上就是清爽大侠为你收集整理的“心脏滴血漏洞”测评经验分享的全部内容,希望文章能够帮你解决“心脏滴血漏洞”测评经验分享所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复