Cloudflare是一家位于美国的网络安全服务商,为包括Uber(优步),Fitbit,1password等在内的众多公司提供网站安全管理,性能优化等服务。近日,Google安全人员在研究中发现:某些情况下,Cloudflare的系统可能会将服务器内存中的数据(包括cookie,API密钥和用户密码等)泄露到网页中——这可谓是数据泄漏的大事。由于会让人回忆起当年OpenSSL的“心脏滴血”事件,也有评论将这次事件称作“云出血(cloudbleed)”。
这就意味着:当用户访问由Cloudflare提供支持的网站时,可能随机获取到他人网络会话(session)中的敏感信息——好比你在一家餐厅里刚刚就座,服务员不仅给你递上了菜单,还赠送了其他某个倒霉客人的钱包。没错,这位服务员就受雇于Cloudflare。
无意发现
这一问题是由Google Project Zero安全团队(该团队似乎长时间专注于漏洞发掘,我们曾前不久报道过他们公布了一个影响Windows GDI库的漏洞)的漏洞猎人(bughunter,也就是国内的白帽子)Tavis Ormandy首先发现的。当时他在搞一个业余项目,无意间在Google搜索引擎的缓存页面中发现了包含完整的https请求,cookie,API密钥和密码在内的大量数据。经过确认后他通知了Cloudflare,后者则迅速成立了团队调查此事。
在一开始,Ormandy怀疑是Cloudflare一款叫做ScrapeShield的应用程序(该程序本是设计用来防御爬虫大量复制网站信息)引发了数据泄露(点击查看Ormandy发布的公告),并在推特上表示他发现了来自各大交友网站的私密信息,知名聊天服务网站的信息和在线密码管理器的数据等。
后来随着Cloudflare调查的深入,他们发现事情并没有那么简单——这种情况已经悄无声息地持续几个月了。
罪魁祸首
Cloudflare在上周四公布的一份报告(点击查看)中给出了调查结果:该事件是由一个编程错误引起,主要体现在Email Obfuscation、Server-Side Excludes和Automatic HTTPS Rewrites这三个功能上。
原来,在此之前Cloudflare曾为其边缘服务器开发一个新的HTML解析器。该解析器用Ragel(一种有限状态机编译器)编写,后转换成C语言源码。这段代码存在一个缓冲区溢出漏洞,可由网页上不成对的HTML标签触发,本是作为指针检查机制来防止内存覆盖的。(如下)
/* generated code. p = pointer, pe = end of buffer */
if ( ++p == pe )
goto _test_eof;
某些情况下,p可能会大于pe,从而避开长度检查,造成缓冲区数据溢出,最终引起了上文所述的信息泄露。Cloudflare工程主管John Graham-Cumming在调查报告中总结道:
“这个问题的根源在于,缓冲区末端检查使用了相等运算符(==),导致指针可以跳过这一段。如果能使用>=而不是==,那么至少可以发现跳过缓冲区尾部的事件。”
另据补充,要致使数据泄露,最后的缓冲区必须以格式错误的脚本或img标签结尾,长度不能超过4KB(否则Nginx会崩溃),并运行上述函数。
为时已晚?
通常此类泄露的信息会隐藏在网页源码中,并不引人注意。这次Ormandy在Google缓存页面中发现了这个问题,意味着很可能在此之前一段相当长的时间里,已经有大量信息被分散泄露到各处,比如爬虫程序,甚至不法分子的手里。
这里简要回顾一下Cloudflare官方报告中给出的时间线:
去年9月22日,启用Automatic HTTP Rewrites函数
今年1月30日,Server-SideExcludes移至新的解析器
今年2月13日,EmailObfuscation部分移至新解析器
今年2月18日,Google向Cloudflare通报了此情况
可以看出,早期的数据泄露事件可能在去年9月就开始了。官方认为,受到冲击最大的时间段可能在今年2月13日开始的4天内,因为当时Automatic HTTP Rewrites还没有开始广泛使用,Server-Side Excludes也只针对恶意IP地址。
不过好在Cloudflare事发后的应对也很迅速。他们在接到通报的47分钟内就禁用了Email Obfuscation。三个小时后,对Automatic HTTPS Rewrites采取了同样的措施。不过对于Server-Side Excludes的终止却稍显棘手,Cloudflare表示他们已经专门发布了一个补丁针对此事。GitHub上已经发布了可能受此漏洞影响的网站名单,对于后续更大范围的补救措施,相信Cloudflare正在落实中。目前尚未有确切的大规模数据以此种途径被不法分子利用的报道,希望一切还不会为时太晚。