欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

利用Semmle QL查询语言发现Facebook Fizz的DoS漏洞

来源:本站整理 作者:佚名 时间:2019-04-15 TAG: 我要投稿


本文讲述的是Semmle公司研究员通过Semmle QL查询语言发现的,关于Facebook Fizz项目的一个拒绝服务漏洞(DoS),漏洞利用原理在于,攻击者可以远程针对目标服务器发送一个经过构造的恶意消息,触发服务器中Fizz程序逻辑实现死循环,最终造成目标服务器的拒绝服务攻击。
Semmle属牛津大学孵化子公司,是一家安全初创企业,其公司宗旨为用独特方法去寻找代码中的漏洞,其理念为将代码当成数据,将分析问题变成对数据库的请求,可轻松自动化地应用于大规模代码的审查。目前,Semmle公司主要有两种产品,一种是代码变量分析环境Semmle QL查询语言,另外一种为深层语义代码审查平台LGTM。
漏洞前导 – Facebook TLS 1.3 协议实现库Fizz
2018年8月,IETF正式发布TLS1.3协议的最终版本RFC 8446,该协议在安全性、性能和隐私方面都有着重大改进,大大提升HTTPS连接的速度性能。这并不是一次大版本更新,而是一次迭代改进。TLS1.3增加了几项新功能,可以使互联网流量更加安全,包括加密握手消息以保证证书私密,重新设计密钥的派生方式,以及零往返连接设置,这使得某些请求比TLS1.2快。
基于庞大的用户群体和随时随地的交流通信机制,为了方便灵活地在Facebook上实现TLS1.3,Facebook官方早前就在内部创建应用了一个用C++14编写的强大、高性能的TLS库 – Fizz,除了TLS1.3附带的协议增强功能外,Fizz还提供了许多功能,包括默认支持异步I/O,以及分散和收集I/O以消除对额外数据副本的需求。
随TLS1.3的发布,Facebook也于2018年8月在Github中开源了Fizz技术,帮助推动TLS 1.3协议在互联网中的应用实现。可以点此参考Facebook官方对Fizz的说明。
漏洞严重性和相关的缓解措施
该漏洞造成的影响是,恶意攻击者可以用TCP方式,针对部署了Facebook Fizz库的任何服务器,远程发送一个恶意消息,触发服务器形成一个无限循环程序逻辑,最终大量消耗资源致使服务器拒绝提供服务。由于攻击者可以利用该漏洞对服务造成中断破坏,但不具备未授权访问可能,所以其被定义分类为DoS类型漏洞。另外,攻击者构造发送的恶意消息大小仅只是64KB多,所以,其攻击成本虽然非常之低,但却能对服务器造成严重后果。
以普通家用级别1M上传速度的互联网带宽连接来看,其每秒就能发送两个这样的恶意构造消息,按每个消息打掉一个CPU来算,组合起一个小型的僵尸网络,用不了多少时间,就能让一个数据中心瘫痪。
漏洞上报后,Facebook非常重视,在第一时间就进行了确认修复。 2019年2月20日的漏洞上报时间,2月25日就在Github中推出了补丁更新。另外Facebook还向我透露,他们在2月20日,就对所有使用了Fizz库的服务器进行了内部缓解修复。
针对该漏洞,除了升级Fizz库外,也没什么具体的缓解措施,建议所有Fizz库用户和企业及时更新,其最新版本为v2019.02.25.00。
PoC验证测试
我用C语言写了一个简单的PoC漏洞利用代码,其原理大概为:首先,开启目标服务器上的一个TCP socket,向其发送一个64KB多一点的恶意消息Payload。之后,待Payload发送完,这个PoC代码会立即关闭socket连接,由于目标服务器会陷入死循环逻辑,所以这点不好验证。当然,我还未对任何现实网站系统进行过验证性攻击,仅只在我自己搭建的部署有Fizz库的服务器应用中进行过测试,尽管如此,由于该漏洞存在于Fizz库的核心代码程序之中,所以,我可以非常确定地认为,https://facebook.com 网站也存在该漏洞。
虽然Facebook已对自身服务系统进行了升级更新,但考虑到广大的Fizz库用户和其不定的修补速度,我会在后续几个星期内选择公布具体的PoC漏洞利用代码。
漏洞分析
该漏洞原因在于,Fizz库源码PlaintextRecordLayer.cpp文件第42行length +=,其+=会导致一个整型溢出。以下为其上下文代码片段:
auto length = cursor.readBEuint16_t>();
if (buf.chainLength() return folly::none;
}
length +=
    sizeof(ContentType) + sizeof(ProtocolVersion) + sizeof(uint16_t);
buf.trimStart(length);
continue;
以上代码从传入的网络包中读取了一个uint16_t格式数据,并把它赋值给length,换句话说,这个length值是攻击者可以控制的。接下来的第39行if语句,初看像一种边界检查,但实际上它是检查是否收到足够多的数据以继续解析,这也就是我们上述漏洞利用代码exploit需要发送64KB数据的原因所在了。也就是说,至少要接收到length传入的字节数之后,其第42行代码才会触发整数溢出。我们的漏洞利用代码exploit会做出 length = 0xFFFB 的设置,这表示,在length +=之后,length的值为0,也可以说,在接下来对trimStart的调用不会消耗任何数据,所以,在对循环的后续迭代中不会产生其它操作流程。
对该漏洞的修补其实非常简单:使用一个比uint16_t类型更大的数据格式来计算加法+,这样,就不会导致整型溢出了。
以上描述并不是漏洞利用代码exploit的详细工作机制,在我看来,length = 0xFFFB的设置是整个漏洞利用机理中比较简单的一点,我觉得,对于大多读者来说,要想弄清构造恶意消息到触发代码整型溢出的过程,可能稍微有点难,但为了安全考虑,待一段时间Fizz用户更新修复后,我会公布完整的exploit代码。
用Semmle QL发现该漏洞
Facebook博客中,其工程师把Fizz描述为“最基础的安全实现”,并列出如错误状态机传输的常见缺陷的C++程序避免技术。我也承认Fizz的总体代码质量非常好,它是流行的底层C++风格,不会出现传统的C程序bug,尤其是,它不涉及任何手工内存存储管理,所以,也不太容易存在常见的缓冲区溢出类问题。另外,Facebook之后还告诉我,他们曾在Fizz代码中执行过Fuzzing缺陷查找和第三方代码审查措施。因此,可以说Facebook Fizz是一个高质量的代码项目,代码团队曾依照最佳实践对其进行开发审查。那么,怎么就存在这么一个漏洞呢?我是如何用QL(查询语言)来发现它呢?

[1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载