FireFox 3.6.x版本之前存在释放后重引用漏洞,此漏洞是由于uxl.dll在处理mChannel标签时,在OnChannelRedirect中对mChannel对象进行创建时,在随后调用Release释放对象,但是释放后没有对指向对象的指针做标记,在随后引用mChannel标签时,因为指针已经释放了,导致call的地址不可读,从而引发UAF漏洞。
漏洞软件:FireFox(火狐浏览器)
漏洞软件版本:FireFox 3.6.16
漏洞Dll模块:xul.dll
漏洞编号:CVE-2011-0065
漏洞类型:UAF
分析环境:Windows XP Sp3
分析工具:Windbg
FireFox符号地址:7e2K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4y4&6L8h3u0G2L8s2y4Q4x3X3g2E0L8%4A6A6L8r3I4S2i4K6u0W2L8%4u0Y4i4K6u0r3k6X3W2J5k6h3k6G2P5l9`.`.
漏洞PoC:
使用Python运行PoC会生成一个HTML文件,用存在漏洞的FireFox打开就会触发漏洞
![](upload/attach/201907/823237_5Y88W4H576EDNJS.png)
先加载一下符号表,用浏览器打开PoC,FireFox会崩溃,然后用WinDbg附加程序,就会到达漏洞触发现场
可以看到这是一片无意义的区域,通过kb堆栈回溯看一下到达无意义区域之前的情况
可以看到栈顶的返回地址,用ub命令查看107f4e75地址之前的指令
看一下call触发的现场
可以看到就是call调用导致程序进入了无意义的区域,call调用的是一处指针,但是寄存器ecx的值是无意义的,ecx是一处虚函数地址,因为指针释放后虚函数的地址变成了无意义的地址,所以造成了UAF漏洞。
我们重新打开PoC,触发异常附加调试
栈回溯看一下
此时栈顶的返回地址是0x107f4e75,用ub命令看一下0x107f4e75之前的指令,漏洞就是出现在xul.dll模块中的
根据C++成员函数this指针调用约定,上面的ecx是虚表基地址,eax是对象地址,call dword ptr [ecx+18h]调用的就是某个对象的方法,这个方法是一个虚函数。
由于每次调试时分配的堆地址不一样,因此为了断点设置的通用性,这里采用函数偏移的断点设置方法,查看xul!gfxFontUtils::ReadNames+0x1471f发现有两个同名的函数
从触发漏洞时栈顶的返回地址0x107f4e75可以知道,这里调用的是:
因此,对0x107e0740下断点
从PoC代码中还可以看到关键函数onChannelRedirect,可以直接在WinDbg中搜索这个函数,发现有很多类都包含了onChannelRedirect
![](upload/attach/201907/823237_7JMUYBJMGHHVCFJ.png)
触发漏洞的类是xul!nxObjectLoadingContext,该类也包含了onChannelRedirect方法,参数也一起列出来了,前两个参数是类对象
![](upload/attach/201907/823237_ZCEEP3E8QVJQMTW.png)
因此,对xul!nsObjectLoadingContent::onChannelRedirect下断点,重新加载PoC,断在了xul!nsObjectLoadingContent::onChannelRedirect处
![](upload/attach/201907/823237_8H8MJPRMG2BBP6X.png)
![](upload/attach/201907/823237_XEFDDJZAAAW5GSH.png)
此时查看三个参数,发现第二个参数是对象067a3e90,其余参数均为0
![](upload/attach/201907/823237_XJK8HN9J9R4GXFF.png)
分析该函数的反汇编代码
![](upload/attach/201907/823237_WG3W7KYCEGNMWZ6.png)
已经直接给出了源码文件和行数,直接查看xul!nsObjectLoadingContent::onChannelRedirect函数的源码,通过FireFox在线的源码地址查找
继续执行下去会断在前面设置的断点xul!gfxFontUtils::ReadNames
根据调试信息的源码路径,可以找到此函数的函数源码,直接在里面找到mChannel对象的引用
fceK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Z5k6#2)9J5k6h3#2G2P5X3W2D9L8r3q4Q4x3X3g2G2M7X3N6Q4x3V1k6J5k6h3I4W2j5i4y4W2M7#2)9J5c8X3#2G2P5X3W2D9L8r3q4Q4x3X3b7I4i4K6u0W2z5g2)9J5k6e0u0Q4x3V1k6X3K9h3I4W2i4K6u0r3N6r3W2H3i4K6u0r3j5$3!0F1N6r3g2F1N6q4)9J5c8X3u0S2M7$3g2Q4x3V1k6K6M7X3x3`.
动态调试一下,先在xul!nsObjectLoadingContent::LoadObject+0xfc下断点
![](upload/attach/201907/823237_MGFBTYMC2QN28D5.png)
执行后断下,可以发现这里引用的对象就是前面的xul!nsObjectLoadingContent::OnChannelRedirect的第二个参数值0x0
![](upload/attach/201907/823237_G4QQR4MCKUDA2XR.png)
单步向下执行就会触发异常,虚表指针被篡改了,导致索引虚函数的时候出错了,进而导致程序崩溃了
![](upload/attach/201907/823237_9SA2U5MASE3ABVN.png)
分析总结:在nsObjectLoadingContent::onChannelRedirect函数中,在mChannel对象未被分配时,会临时赋予一个新的对象值,而该新对象值在函数返回后会被回收释放,导致mChannel成为一个悬挂指针。
程序又在后面的nsObjectLoadingContent::LoadObject函数中引用到该悬挂指针mChannel,最终导致UAF漏洞触发,造成程序崩溃。
为了实现任意代码执行,需要在mChannel对象释放后,用可控数据占坑填充它,因此,可以在OnChannelRedirect函数调用完成后,紧跟着申请一块大小相同的内存。
执行后,虚表指针就会被0x0c0c001c填充,从而控制程序执行流程
后面利用Heap Spray技术将Shllcode喷射到0x0c0c0034的位置就可以实现任意代码执行
将Shellcode用0x41414141填充,在XP系统上可以直接放payload执行,在Windows 7上开启了DEP保护,可以结合ROP技术绕过。
EXP分析
FireFox的漏洞补丁代码是开源的,可以在之前的网站找到
可以看到,补丁代码添加了对mChannel对象的判断,当mChannel=0时直接返回,直接避免后面的赋值占位操作,从而防止UAF漏洞的发生,就是在指针释放后及时将指针赋Null。
UAF漏洞在浏览器漏洞挖掘中非常常见,这跟JS和浏览器引擎有很大关系,在指针释放后再申请相同大小的内存,系统会将释放的地址进行分配,来提高系统运行速度,因此可以修改被释放的内存数据,如果被释放的指针继续被使用,则会造成UAF漏洞。
通过UAF漏洞,可以造成一些任意内存的修改,结合代码特点,可能会造成任意内存的读取或者,严重的就可以造成任意命令的执行,获得shell。
此漏洞的分析参考了泉哥和K0的文章,在分析过程中,遇到一个问题就是FireFox的符号表一直下载失败,最终是下载了一份符号表加载的,如果有师傅可以加载成功留言一下。
《漏洞战争》
https://bbs.pediy.com/thread-216198.htm
f54K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4K9r3g2J5k6h3W2K6K9K6m8K6K9r3I4Q4x3X3g2@1L8%4m8Q4x3V1k6H3L8%4y4@1i4K6u0r3x3U0l9I4y4#2)9J5k6o6l9#2i4K6u0V1x3e0b7`.
github博客地址:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-7-12 15:47
被0xbird编辑
,原因: