2014年4月7日,OpenSSL宣布的OpenSSL 1.0.2-beta及1.0.1系列(除1.0.1g)的所有版本中,在其所实现的TLS心跳扩展存在严重的内存处理错误。它可以被用于让每个心跳包显示应用程序至多64K Byte的内存内容。它的CVE号为CVE-2014-0160。
该漏洞是通过发送一个畸形的心跳请求至服务器,以引起服务器内存响应而引发。由于缺乏边界检查,OpenSSL不会验证心跳请求的有效性,从而可以带给攻击者不恰当的服务器响应。
自2011年12月31日,漏洞就已经存在,而且随着OpenSSL版本1.0.1于2012年3月14日释出,有缺陷的代码被广泛使用。通过读取网络服务器内存,攻击者可以访问敏感数据,从而危及服务器及用户的安全。潜在的敏感数据,包括服务器的专用主密钥,可使攻击者得以通过被动中间人攻击,解密当前或存储的传输信息(如果服务器和客户端未使用完全正向保密),或使用了完全正向保密时发动主动中间人攻击。攻击者无法控制服务器返回的数据,因为服务器会使用一个随机内存块作为响应。
漏洞还可能暴露其他用户的敏感请求和响应,包括用户任何形式的POST请求数据,会话cookie和密码,这能使攻击者可以劫持其他用户的服务身份。在其披露时,约有17%或五十万通过认证机构认证的互联网安全网络服务器被认为容易受到攻击。电子前哨基金会, Ars Technica,和布鲁斯·施奈尔都认为心脏出血漏洞是“灾难性的”。
Heartbleed是什么?
说起“心脏出血”要从OpenSSL说起了,实际上Heartbleed 并不是病毒,而是 OpenSSL 的一个漏洞。众所周知,OpenSSL 是一个安全协议,它可以对用户与大多数网络服务所提供的服务器之间的通信进行加密。因为很多网站(例如google等)采用的是 OpenSSL 来保护敏感的用户信息,这就让大量的用户信息处于随时被窃取的危险境地。
黑客利用这个漏洞,就能够从大量包含用户名、密码和其他敏感信息的数据库中窃取数据。
剖析 Heartbleed的“所作所为”
既然上文说了,如果要弄清楚Heartbleed 的“所作所为”,笔者先来解释一下什么是 SSL,从而进一步了解OpenSSL。
SSL 是安全套接层 (Secure Sockets Layer) 的缩写,是一个安全标准,支持信息在用户与服务之间安全传递,确保信息免遭第三方截获。OpenSSL 是一个开源项目,由开源爱好者和志愿者使用来自开发社区的信息进行更新和维护。
如果要使 SSL 发挥作用,计算机需要与服务器进行通信。为此,它会发送称为“heartbeat”(心跳)的信息。heartbeat 所做的就是向服务器发送特定信号以确定服务器是否联机。如果服务器联机,它会向计算机发送回该信号,让用户可以尽享安全的通信。计算机和服务器会定期发送 heartbeat 以确定用户和服务器没有脱机。
Heartbleed 会向服务器发送恶意 heartbeat,以此来“恶搞心跳”。实质上是“诱骗”服务器向发送该恶意 heartbeat 的用户传回一个随机内存块,其中可能包含一组地址、用户名和密码。令人担忧的是,这些凭据中的一些可能属于管理该服务器的公司。这就为黑客提供了一种通过互联网访问和窃取信息的途径。
有多严重?
这一漏洞的严重性不容小觑。节选来自Heartbleed的官方说明:OpenSSL在Web容器如Apache/Nginx中使用,这两的全球份额超过66%。一些大型的互联网公司常使用 OpenSSL,而这曾经被认为是最安全的数据传输手段之一。不仅如此,众多网络路由器厂商包括 Cisco Systems 与 Juniper Networks等,纷纷发布了紧急公告,列出一系列受此漏洞影响的路由器产品。虽说这些产品由于使用旧版SSL,厂商也表示会尽快更新补洞,但对于网管人员来说,着实是个令人头大的问题。据悉,有的黑客一年前就已经在利用这个漏洞了,获取到了不少大网站的敏感信息。
Bug类型:
该漏洞被归为缓冲过度读取。缓冲过度读取错误是软件可以读取比应该被允许还多的数据。
OpenSSL版本1.0.1g增加了一些边界检查,以防止过度读取缓冲。例如,测试
if (1 + 2 + 16 > s->s3->rrec.length) return 0; /* silently discard */ |
已添加在行
hbtype = *p++; |
的前面。 更改的完整列表,请参阅git.openssl.org。
更多信息:请参考知乎上的讨论:http://www.zhihu.com/question/23328658?sort=created
下面是一段技术分析:http://blog.existentialize.com/diagnosis-of-the-openssl-heartbleed-bug.html
When I wrote about the GnuTLS bug, I said that this isn't the last severe TLS stack bug we'd see. I didn't expect it to be quite this bad, however.
The Heartbleed bug is a particularly nasty bug. It allows an attacker to read up to 64KB of memory, and the security researchers have said:
Without using any privileged information or credentials we were able steal from ourselves the secret keys used for our X.509 certificates, user names and passwords, instant messages, emails and business critical documents and communication.
How could this happen? Let's read the code and find out.
The bug
The fix starts here, in ssl/d1_both.c:
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 */
So, first we get a pointer to the data within an SSLv3 record. That looks like this:
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;
Records have a type, a length, and data. Back to dtls1_process_heartbeat:
/* Read type and payload length first */ hbtype = *p++; n2s(p, payload); pl = p;
The first byte of the SSLv3 record is the heartbeat type. The macro n2s takes two bytes from p, and puts them in payload. This is actually the length of the payload. Note that the actual length in the SSLv3 record is not checked.
The variable pl is then the resulting heartbeat data, supplied by the requester.
Later in the function, it does this:
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;
So we're allocating as much memory as the requester asked for: up to 65535+1+2+16, to be precise. The variable bp is going to be the pointer used for accessing this memory. Then:
/* Enter response type, length and copy payload */ *bp++ = TLS1_HB_RESPONSE; s2n(payload, bp); memcpy(bp, pl, payload);
The macro s2n does the inverse of n2s: it takes a 16-bit value and puts it into two bytes. So it puts the same payload length requested.
Then it copies payload bytes from pl, the user supplied data, to the newly allocated bp array. After this, it sends this all back to the user. So where's the bug?
The user controls payload and pl
What if the requester didn't actually supply payload bytes, like she said she did? What if pl really is only one byte? Then the read from memcpy is going to read whatever memory was near the SSLv3 record and within the same process.
And apparently, there's a lot of stuff nearby.
There are two ways memory is dynamically allocated with malloc (at least on Linux): using sbrk(2) and using mmap(2). If the memory is allocated with sbrk, then it uses the old heap-grows-up rules and limits what can be found with this, although multiple requests (especially simultaneously) could still find some fun stuff1.
The allocations for bp don't matter at all, actually. The allocation for pl, however, matters a great deal. It's almost certainly allocated with sbrk because of the mmap threshold in malloc. However, interesting stuff (like documents or user info), is very likely to be allocated with mmap and might be reachable from pl. Multiple simultaneous requests will also make some interesting data available.
And your secret keys will probably be available:
Just cracked @CloudFlare ’s challenge: https://t.co/8ZPSxyKF4D . I wonder when they’ll update the page.
— Fedor Indutny (@indutny) April 11, 2014
The fix
The most important part of the fix was this:
/* Read type and payload length first */ if (1 + 2 + 16 > s->s3->rrec.length) return 0; /* silently discard */ hbtype = *p++; n2s(p, payload); if (1 + 2 + payload + 16 > s->s3->rrec.length) return 0; /* silently discard per RFC 6520 sec. 4 */ pl = p;
This does two things: the first check stops zero-length heartbeats. The second check checks to make sure that the actual record length is sufficiently long. That's it.
Lessons
What can we learn from this?
I'm a fan of C. It was my first programming language and it was the first language I felt comfortable using professionally. But I see its limitations more clearly now than I have ever before.
Between this and the GnuTLS bug, I think that we need to do three things:
- Pay money for security audits of critical security infrastructure like OpenSSL
- Write lots of unit and integration tests for these libraries
- Start writing alternatives in safer languages
Given how difficult it is to write safe C, I don't see any other options. I would donate to this effort. Would you?
-
This section originally contained my skepticism about the feasability of a PoC due to the nature of how the heap works via sbrk. Neel Mehta has validated some of my concerns, but there are many reports of secret key discovery out there.
相关推荐
**Heartbleed漏洞详解** Heartbleed漏洞源于OpenSSL 1.0.1版本中的一个错误实现,具体是CVE-2014-0160。在心跳扩展过程中,服务器或客户端可能会返回超过预期长度的数据,泄露私密信息,如服务器的私钥、用户的登录...
**Heartbleed漏洞详解** Heartbleed,全称为OpenSSL Heartbleed Bug,是2014年4月被公开的一个严重安全漏洞,主要影响使用OpenSSL库的HTTPS服务器。这个漏洞源于OpenSSL心脏出血(Heartbeat)扩展的一个错误实现,...
### SSL心脏出血漏洞详解 #### Heartbleed 漏洞概览 2014年4月7日,OpenSSL项目发布了一项重要的安全公告,披露了在其1.0.1版本中存在的一个严重漏洞(CVE-2014-0160),这一漏洞被称为“Heartbleed(心脏出血)”...
**OpenSSL 心脏滴血漏洞(CVE-2014-0160)详解** OpenSSL 是一个强大的安全套接层(SSL/TLS)和传输层安全(TLS)库,广泛应用于服务器端,为互联网上的通信提供加密。然而,在2014年,一个名为“心脏滴血”...
另一类是安全漏洞,比如著名的Heartbleed(OpenSSL中的TLS/DTLS心脏出血漏洞),以及GHOST(GETHOSTBYNAME的栈溢出漏洞)等,这些漏洞可能被恶意攻击者利用,执行任意代码或获取敏感信息。 ### glibc漏洞的危害 1....
OpenSSL 1.0.2g 版本是该库的一个稳定版本,发布于2016年,修复了多个安全问题,包括著名的“心脏出血”漏洞的后续修复。 1. **SSL/TLS 协议** - SSL 和 TLS 是互联网上广泛使用的加密通信协议,用于在客户端和...
此版本修复了一些已知的安全漏洞,比如著名的“心脏出血”漏洞(Heartbleed),确保了用户数据的安全性。此外,它还改进了多线程支持,增强了与不同操作系统和硬件平台的兼容性。 3. **关键特性** - **证书管理**...
3. **安全审计**:通过`nassl`,开发者可以进行深度安全审计,比如检测已知漏洞(如心脏出血Heartbleed),或者进行自定义的弱密码扫描。 4. **记录和重放**:`nassl`支持记录SSL/TLS会话,并能够重放这些会话,这...
该库不仅支持标准的SSL/TLS协议,还涵盖了各种扩展和漏洞利用场景,如心脏出血(Heartbleed)漏洞,这对于安全研究人员和渗透测试人员来说非常有用。 **2. Python版本兼容性** “cp38”表示此版本的nassl库是针对...
例如,著名的“心脏出血”(Heartbleed)漏洞就出现在1.0.1系列的某个版本,而1.0.1h则是对这个漏洞的修复版本之一。这个版本的发布,强调了持续维护和安全更新的重要性。 三、源码分析 1. `openssl-1.0.1h.tar.gz...
定期检查更新,及时修复任何已知的安全漏洞,例如著名的“心脏出血”漏洞(Heartbleed)。1.1.1g是一个安全版本,但仍然建议关注官方发布的更新公告。 7. **编译自定义配置** 对于有特殊需求的开发者,可以自定义...
1.0.2n 版本可能会包含对某些已知漏洞的修复,比如 Heartbleed(心脏出血)漏洞,该漏洞曾影响了早期版本的 OpenSSL。 3. **源码编译**:使用 Visual Studio 2013 编译 OpenSSL 源码是为 Windows 平台构建本地库的...
例如著名的“心脏出血”(Heartbleed)漏洞就出现在较早的OpenSSL版本中,提醒我们及时更新软件以保持系统安全。 10. **编译与安装**: 安装OpenSSL涉及下载源代码、配置编译选项、编译和安装步骤,这对于理解其工作...
首先,OpenSSL 1.0.1g是OpenSSL的一个特定版本,发布于2014年4月,主要修复了心脏出血(Heartbleed)安全漏洞。这个版本对开发者来说尤其重要,因为它确保了iOS应用在进行网络通信时的安全性,避免了可能的数据泄露...
例如,著名的“心脏出血”(Heartbleed)漏洞发生在OpenSSL 1.0.1版本,而1.0.2系列在发布时已经修复了这个问题。通过对比不同版本的源代码,我们可以了解如何识别和修复安全问题。 **编译与调试** 在 `Configure` ...
然而,SSL/TLS也面临一些安全挑战,如心脏出血(Heartbleed)漏洞,这要求管理员定期更新和修补服务器的SSL/TLS配置。 总结来说,SSL是一种保证网络通信安全的重要技术,通过加密数据和验证服务器身份,为用户提供...
1. SSL/TLS协议的详细检查:能够查看和解析证书链,检查证书的有效性,检测已知漏洞,如心脏出血(Heartbleed)等。 2. 客户端和服务器端的握手模拟:模拟客户端发起连接,服务器响应,从而测试服务器的SSL/TLS配置...
6. **OpenSSL的安全性**:尽管OpenSSL在历史上曾出现过如Heartbleed(心脏出血)这样的安全漏洞,但其社区反应迅速,及时修复了这些问题。保持OpenSSL库的更新至关重要,以防止潜在的安全风险。 7. **OpenSSL的版本...
3. **安全性考虑**:确保代码的安全性,避免已知的漏洞,如心脏出血(Heartbleed)等。 4. **性能优化**:考虑如何提高加密和解密的速度,以及降低CPU和内存的使用。 5. **证书管理**:实现证书的生成、验证和存储...