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

把握机会之窗:看我如何获得Chrome 1-day漏洞并实现利用

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

概述
针对Chrome浏览器来说,当发现一个漏洞后,将首先在v8源代码树中进行修复,随后再发布一个新的稳定版本Chrome,而在这两个过程期间,攻击者完全可以针对特定漏洞,开发出一个可用的漏洞利用方法,本文主要探讨了攻击者利用这一时间差开展攻击的可能性。
Chrome发布计划
Chrome浏览器有一个相对非常紧密的新版本发布周期,如果发现浏览器存在严重漏洞需要进行更新,他们会每隔6周发布一个新的稳定版本。然而,Chrome使用了开源的开发模型,尽管安全修复程序可以被立即更新到源代码树中,并且立即可见,但这些更新部分还需要一定时间在Chrome的非稳定版本渠道中进行测试,然后才可以通过自动更新机制将其推送到大多数用户群体所使用的稳定版本上。
正因如此,攻击者就获得了一个机会窗口,这一窗口的时间根据漏洞发布时间而定,从几天到几周不等。其中,漏洞的详细信息几乎是完全公开的,但在公开之后,大部分用户所使用的Chrome都非常脆弱,因为他们此时还无法获得补丁更新。
开源补丁分析
对于攻击者来说,如果通过v8的Git Log查看,可能会得到大量有效的信息,他们的体验非常良好。然而,其中的一个变化立即引起了我的注意。该修复程序具有以下提交信息:
[TurboFan] Array.prototype.map wrong ElementsKind for output array.
这表明,如果要进入到相关Chromium问题的跟踪器,这一行为将受到限制,这一限制可能会持续数月。但是,在这里已经包含了可能允许攻击者迅速开发漏洞利用方式的所有信息,因此这也被攻击者作为了最终的目标。TurboFan是v8的优化JIT编译器,近期也成为了一个热门的目标。
数组漏洞的利用成功概率相对较大,这样的提示可能暗示了元素类型之间存在类型混淆的问题,而这一问题可能比较简单的复现。在这一补丁中,还包含一个有效触发漏洞的回归测试,这也能有助于缩短漏洞利用的开发时间。
我们看到,唯一修改过的方法是src/compiler/js-call-reducer.cc中的JSCallReducer::ReduceArrayMap:
Reduction JSCallReducer::ReduceArrayMap(Node* node,
                                         const SharedFunctionInfoRef& shared) {
   Node* original_length = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
        effect, control);
 
 +  // If the array length >= kMaxFastArrayLength, then CreateArray
 +  // will create a dictionary. We should deopt in this case, and make sure
 +  // not to attempt inlining again.
 +  original_length = effect = graph()->NewNode(
 +      simplified()->CheckBounds(p.feedback()), original_length,
 +      jsgraph()->Constant(JSArray::kMaxFastArrayLength), effect, control);
 +
    // Even though {JSCreateArray} is not marked as {kNoThrow}, we can elide the
    // exceptional projections because it cannot throw with the given parameters.
    Node* a = control = effect = graph()->NewNode(
       javascript()->CreateArray(1, MaybeHandle()),
       array_constructor, array_constructor, original_length, context,
       outer_frame_state, effect, control);
JSCallReducer在TurboFan的InliningPhase期间运行,其ReduceArrayMap方法尝试使用内联代码替换对Array.prototype.map的调用。代码中添加的注释仅仅是描述性的,在添加的代码中,增加了一个检查机制,以验证数组的长度是否小于kMaxFastArrayLength(其长度为32MiB)。该长度将传递到CreateArray,后者会返回一个新的数组。
针对于具有特定特征的阵列的存储,v8引擎会对其进行不同的优化。例如,PACKED_DOUBLE_ELEMENTS是用于仅具有双元素且没有孔的数组的元素种类。它们作为连续的数组存储在内存中,可以为map等操作生成高效的代码。不同元素种类之间的混淆,是产生安全漏洞的一大常见原因。
那么,如果长度大于kMaxFastArrayLength,为什么会出现问题呢?因为CreateArray将返回一个具有该长度的dictionary(字典)元素种类的数组。该字典主要用于大型数组和稀疏数组(Sparse Array),基本上是哈希表。但是,通过为其提供正确的类型返回,TurboFan将尝试为连续数组生成优化代码。这也是许多JIT编译器漏洞的常见特点:编译器根据类型反馈进行优化,但是这里存在着一个极端情况,就是允许攻击者在生成的代码的运行时中断假设。
由于字典和连续元素种类具有两种截然不同的后备存储机制,因此这将允许产生内存损坏的问题。实际上,输出的数组将是一个较小的字典(这里是指其在内存中的大小,而并非它的长度属性),将会被优化的代码访问,在访问的过程中会假定它是一个较大的连续区域(同样,是指其在内存中的大小)。
我们查看修复后代码中包含的回归测试,它将为map函数提供反馈,用于具有连续存储的数组(第6-13行),然后在通过TurboFan进行优化之后,使用具有足够大的数组对其进行调用,以便使map的输出最终符合dictionary(字典)元素类型。
// Copyright 2019 the V8 project authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // Set up a fast holey smi array, and generate optimized code.

[1] [2]  下一页

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