openssl heartbeed到底是怎么回事?

本文深入剖析了SSL/TLS协议中的“心脏出血”漏洞,解释了该漏洞如何导致信息泄露,包括用户凭证和个人数据等敏感信息,并探讨了其对网银及电商支付安全的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      平常上普通网站的时候,用的是http协议,http协议是明文的,你拿抓包工具,比如wireshark可以清楚的看到你浏览的网页是怎么封装在IP报文里面的。

但凡和保密有关的,比如网银,比如电商网站的支付界面,用的是https协议,https传递的是密文,这个是通过SSL/TLS协议来实现的。而当今互联网上,绝大部分公司采用的是openssl。

     根据RFC6520, TLS(还有DTLS)里面有一个心跳机制,所谓心跳,就是你的浏览器和网站的https server可以互相周期性的打招呼,在对方下线的时候自己可以知道。这个心跳机制除了打招呼的功能以外,还顺带实现了一个检测PMTU的功能。什么叫PMTU?我们知道,浏览器和网站的https server之间跨了一张庞大的internet(windows上大家可以用tracert www.youkuaiyun.com看看你的电脑和csdn之间隔了那些路由器)。PMTU指的是这两点之间可以单次传送的数据的最大尺寸。这个PMTU发现是怎么实现的呢?按照RFC6520,心跳请求报文里面可以带上一定长度的载荷(payload),心跳的响应方收到这个报文以后,如果觉得这个载荷的大小自己是可以接受的,就原样把这段载荷拷贝到心跳应答报文里面去,这样请求方收到应答以后就知道这个尺寸对方是能处理的,请求方可以一直增加载荷的长度,直到最后收不到应答为止,这样最大的长度就确定下来了。那么响应方是怎么知道这个载荷到底有多长呢?今天的应用层协议通常是通过字符串来传递信息的,只要找到换行回车或者xml tag之类的标记就可以了,象TLS这种底层协议是基于二进制的,它通常在协议报文里面的相对固定位置上放一个整数,直接告诉对方后面的字段有多长就可以了。但是这种方法有个缺陷,如果我实际只发送了10个字节的载荷,但是我非要在那个指示长度的整数里告诉你其实我发了1千个字节,那会怎么样?这种情况在所有二进制协议里面天天遇到,处理方式很简单,就是接收方要把你指示的长度和这个报文里面剩下部分的长度作个比较,如果前者比后者大,对不起,这是一个错误报文,丢弃就是了。

    可是故事中这段代码的作者是个新手(一个在读博士生,而openssl的初始作者是Eric Yong,兄弟10多年前移植过他的crypto库,绝对是C语言代码的典范),显然有点缺乏常识,他直接信了过来的报文的长度字段,然后根据这长度,从心跳请求报文中的放载荷的第一个位置开始把载荷拷贝到自己的响应报文中。那诸位要问了,既然报文中只有10个字节的信息,那多出来的990个字节从那里来?这是故事的关键!就从这10个字节后面来,首先是同一个报文中后面的部分,反正是发送请求方自己填的内容,不会泄漏服务器上的其他信息,然后呢,如果越出了当前请求报文的边界,那就跑到其他地方去了,其他地方是什么地方呢?这取决于openssl的buffer管理方案,如果他专门开了一个pool或者一块很大的连续地址空间来提供报文缓冲区,那么这个报文的地址后面是其他报文,会把其他报文的内容拷贝出来,如果放报文的内存和其他用途的内存一起管理,那拷贝出来的东西就五花八门了。

   有同学要问了,那我的私密信息被copy出来的可能性有多大?以网银举例,这个可能性还真不小。假设搞攻击的家伙把尺度用足(那个指示长度的字段有两个字节,转化程整数就是一个unsigned short,最大是65535),以平均525字节一个报文缓冲区算,一下子能拷贝出125个。要知道,平常我们上网银,基本上就是登录,转账,支付,下线走人,那么缓存在系统中的报文大部分都是干货。另外,很多大网站有专门的认证服务器,这样的后果是这台服务器上取出来的信息里面没有八卦,全是认证信息。

   但是别急!即便你上网银的所有报文都被人家看了一个遍,他可能还是偷不了你的钱。首先,你上网银的时候除了用户名,密码,通常还有一个USB设备或者token,这些设备产生出来的信息每次都是不一样的,知道了也没用。所以即使他知道你的帐号,没有这几样设备也是白搭。以交易过程中的数字签名为例,你的私钥保存在UKey中,不要说在网络中传输了,即便在你自己的电脑上也是没办法读取的,每次进行签名时,你的浏览器是把需要签名的材料交给UKey,由UKey中的嵌入式处理器计算出签名后返回给浏览器,然后再出示给服务器方的。由于待签名的材料每次都不一样,所以签名的结果也不一样。所以黑客也就是能知道你事发当时账上有多少钱而已,此后他是无法登陆入你的帐户的。

  如果没有UKey或者token是不是就没救了呢?也不是。只要密码不直接在网上传输就没事。最基本的认证方法是浏览器把你的密码和网站自己生成的一个随机数一起做一次单向运算,然后送过去。因为有随机数,这个单向运算结果每次都不一样。这样黑客是无法通过这次发现的漏洞来获取密码的。不过,问题在于很多网站的设计者认为反正openssl已经加密了,然后直接把用户名,密码在网上传递。这种情况就比较悲剧了。我猜想这样做的网站绝对是多数。谁能预料到会出这么大的漏子呢?

  网银没问题了,那支付宝呢?我不知道。但是只要他没有傻到在网上传递你的密码(其实也不傻),那么也没啥风险。否则的话,问题就大了,你想想,全中国每秒钟有多少人在登录支付宝啊。

  当然,刚才的乐观分析都建立在拷贝出来的是其他报文的基础上,如果拷贝到别的地方,比如说最悲观的情况,如果网站把用户名密码这张表缓存到内存中,然后凑巧这段内存被人拷贝出来了,那就只能自求多福了。不过这样干的人少之又少,我猜想在web的世界里,用户认证通常不会是性能瓶颈,直接从数据库里面按需索取就可以了。

  另外,做安全的人通常有一些行规,比如敏感信息不会长期保存在内存里,密码什么的一旦用好就会马上抹掉,这也可以保证这次的损失不会太大。

  附上有缺陷的原代码,请看2593和2616行。

 

 ==========================================================================================================

-查看了openssl的内存管理代码,没有专门的报文缓冲区池,缺省情况是所有存储分配最后直接调用malloc,这样后果挺严重了,因为认证过程中的证书,网站自己的私钥,以及所有解密后的内容都是动态分配的内存中存放的,能取出来的东西太多了。

 -漏洞出来的时候,大家都担心泄漏用户信息,其实更应该担心泄漏网站自己的信息,比如服务器自己的私钥,攻击者有可能用这些信息建一个假冒的网站,然后钓取用户的密码。

-另外,许多网站考虑到底层已经有https加密,直接明文传递密码。攻击者直接看请求看取出来的url就能轻而易举的发现大量账户信息,后果难以设想啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值