当前位置:首页 > 探索

openssl 信息泄露漏洞

2014年4月7日,信息泄OpenSSL项目组发布了一个安全公告,露漏编号CVE-2014-0160。信息泄当时没人意识到,露漏这个被命名为"心脏出血"(Heartbleed)的信息泄漏洞,会在接下来几周内让半个互联网陷入恐慌。露漏攻击者只需要发送一个畸形的信息泄TLS心跳请求包,就能从服务器内存中读取最多64KB的露漏数据。这64KB里可能包含什么?信息泄私钥、会话凭证、露漏用户密码、信息泄甚至其他用户提交的露漏表单内容——服务器内存里有什么,就能读到什么。信息泄

问题的露漏根源出在OpenSSL对TLS心跳扩展的实现上。RFC 6520定义的信息泄心跳机制本意是让通信双方确认连接是否存活,客户端发送一个心跳请求,附带一段数据和一个长度字段,服务器收到后原样返回这段数据。正常逻辑下,服务器应该检查请求中声明的长度是否与实际携带的数据长度一致。但OpenSSL的tls1_process_heartbeat函数没有做这个校验。它直接信任了请求中声称的长度payload,然后从内存缓冲区中拷贝payload字节返回给客户端。如果攻击者声称有65535字节,但实际只发送了1字节,服务器就会从内存中多读65534字节,连同那1字节一起发回去。

谁写的这段代码,为什么没被发现

这段有问题的代码是德国开发者Robin Seggelmann在2011年底提交的,2012年初合并进OpenSSL主干。Seggelmann后来接受采访时说,这是一个"疏忽"——他忘了在边界检查中加入对长度字段的验证。代码审查环节也没有人注意到这个细节。OpenSSL当时的开发模式相当松散,核心维护者只有几个人,大部分提交靠志愿者审查。一个看起来无关紧要的心跳扩展,没有引起足够重视。

这暴露了一个很现实的问题:开源基础设施的安全,往往依赖于极少数人的义务劳动。OpenSSL被全球绝大多数HTTPS网站使用,但2014年之前,这个项目每年获得的捐款不到2000美元。代码量庞大、审查资源有限、缺乏系统性的安全测试——心脏出血不是偶然,是必然。

漏洞的实际影响范围

心脏出血影响的是OpenSSL 1.0.1到1.0.1f版本,以及1.0.2-beta。1.0.0及更早版本不受影响,因为心跳扩展是1.0.1才引入的。修复方式很简单:升级到1.0.1g,或者在编译时加上-DOPENSSL_NO_HEARTBEATS禁用心跳功能。

但修复本身只是第一步。真正的麻烦在于善后:服务器私钥可能已经泄露,意味着攻击者可以解密之前截获的HTTPS流量,或者伪造服务器身份进行中间人攻击。换私钥意味着重新签发证书,对于大型网站来说,这是一整套连锁操作。而且你无法知道自己的服务器是否已经被攻击过——心跳请求在日志里和正常请求几乎没有区别。

当时的一个检测手段是专门的心跳测试工具,比如ssltest.py或Nmap的ssl-heartbleed脚本,向目标服务器发送恶意心跳包,看返回的数据是否超出预期。很多安全团队那几天都在批量扫描自己的资产,结果参差不齐。有人发现内部测试环境还在跑老版本,有人发现某个边缘业务用了自带OpenSSL的旧版nginx。这种"你以为已经升级完了,结果角落里还藏着一个"的情况非常普遍。

这件事留下了什么

心脏出血之后,Linux基金会成立了核心基础设施计划(CII),专门给OpenSSL这类关键开源项目提供资金。OpenSSL项目组也引入了更正式的代码审查流程和安全审计。但更深远的影响在观念层面:整个行业开始意识到,互联网的加密基石不能建立在几个人的业余时间上。

从技术角度看,这个漏洞的教训很朴素——永远不要信任外部输入的长度字段。任何从网络接收的数据,在用于内存操作之前,必须与实际缓冲区大小做校验。这个原则写进教科书几十年了,但真正落实到每一行代码,仍然需要人、时间和制度来保障。

分享到: