利用特殊协议加载本地文件, 绕过 HTML5 沙箱, 打开弹窗诸事

原文链接:https://www.brokenbrowser.com/abusing-of-protocols/

原作者:Manuel Caballero

译:Holic (知道创宇404安全实验室)

在 10 月 25 日,研究员 @MSEdgeDev twitter 了一个链接,成功引起了我的注意,因为我点击那个链接的时候(在 Chrome 上),Windows 应用商店会自动打开。这对你来说也许不足为奇,但它足以让我感到惊讶。

在我印象中,Chrome 有这样一个健康的习惯,在打开外部程序之前询问用户是否打开外部程序。但是这次的情况是它直接打开了相应程序,而且没有警告。

这次的差别反应引起了我的主页,因为我从来没有允许 Chrome 打开 Windows 商店。有一些插件和协议会自动打开,但我从来没有允许过 Windows 商店这一应用。

缩短的 Twitter 链接重定向至 https://aka.ms/extensions-storecollection ,然后再一次重定向到:ms-windows-store://collection/?CollectionId=edgeExtensions ,Interesting ~.

这一协议我不甚了解,因此我马上试着找到与该协议存在多处关联的地方:注册表。搜索 “ms-windows-store” 立即返回了我们在 PackageId 中的字符串,这似乎是 Windows 应用商店的程序。

注意我们也在一个名为 “Windows.Protocol” 的键之中,我稍微上下滚动了一些,以便看看有没有其他的应用程序在其中。然后我发现他们很多拥有自己的注册协议。这便是极好的,因为这直接从浏览器打开了一个新的攻击面。然而我们按 F3 看看我们是否找到其他的匹配项。

似乎 ms-windows-store:协议也接受搜索参数,所以我们可以试着直接从 Google Chrome 打开我们的自定义搜索。事实上,Windows 应用商店应用程序似乎使用了 Edge 的引擎渲染 HTML,这也是很有趣的地方,因为我们可能尝试进行 XSS 攻击,亦或是本地程序,发送一大堆数据然后看看会发生什么。

但是现在我们不会这么干,我们回到注册表上来,按下 F3 看看我们能找到什么。

这也是很有意思的,因为如果它们用字符串 “URL:”前缀的话,它会给我们快速找到更多的协议的线索。让我们将搜索重置为 “URL:”,看看我们得到什么。按下 [HOME] 键回到注册表的顶部,搜索 “URL:” ,将马上返回递归个匹配的 “URL:about:blank”,以及顺便确认下我们还没疯掉。

再次按下 F3 ,我们找到了 bingnews: 协议,但是这次 Chrome 向我们确认了是否要打开它。没毛病,让我们在 Edge 上试试看会发生什么。它打开了!在注册表中下一个匹配的的是 calculator: 协议。这会生效吗?

Wow!exploit 的作者们肯定好气啊。它们将弹出什么程序呢?calcnotepad 可以打开,而且没有产生内存损坏。现在 cmd.exe 已经弃用,而是采用了 powershell。微软移除了你们这群人的乐趣 ? 。

这便是枚举所有可能被加载的协议的时候了,先去看看哪些程序接受参数,那么我们可以尝试注入代码(二进制或者纯 Javascript,取决于应用程序的编码方式和他如何处理参数)。有很多有趣的玩法,如果我们继续寻找协议,我们将发现大量的能打开的程序(包括 Candy Crush,我还不知道我电脑上有这东西)。

通过按几次 F3 ,我受益匪浅。例如,有一个 microsoft-edge:协议在新标签中加载 URL。这看起来似乎并不重要,直到我们记住 HTML 页面应有的限制。弹出窗口拦截器会阻止我们打开 20 个 microsoft-edge:http://www.google.com 标签吗?

[ PoC – 在微软 Edge 浏览器上弹窗 ]

那么 HTML5 沙箱又怎样呢?如果你不熟悉它,它只是一种使用 iframe 沙箱属性或者 http header 的沙箱属性对网页施加限制的方法。例如,如果我们想在 iframe 中渲染内容并且确保它不运行 javascript (甚至不打开新标签),我们只需要使用此标签:

<iframe src=”sandboxed.html” sandbox></iframe> 

然后渲染的页面将被完全限制。它基本上只能渲染 HTML/CSS ,但是没有 javascript 或者其他访问接触到像 cookie 这样的东西。事实上,如果我们使用沙盒粒度,并且至少允许打开新窗口/标签,他们应该全都继承沙箱属性,以及从 iframe 点击链接打开的依然受沙盒限制。然而,使用 microsoft-edge 协议完全绕过了这一点。

[ PoC – 在 微软 Edge 浏览器上绕过 HTML5 沙箱 ]

很高兴看到 microsoft-edge 协议允许我们绕过不同的限制。我更深入研究,但你可以一试!这是发现之旅,纪念一条 tweet 激发了我研究的动力,而且最终给我们真正值得进行更多研究的材料。

我继续在注册表中按下 F3 键,发现了 read: 协议,它引起了我的注意力,因为当阅读它的 (javascript)源码时,它可能有潜在的 UXSS 漏洞,但是尝试的过程中 Edge 一次次地崩溃了。它崩溃太多次了。例如,将 iframe 的 location 设置为 “read:” 就足以使浏览器崩溃,包括所有选项卡。想看看吗?

[ PoC – Crash on MS Edge ]

OK,我很好奇发生了什么,所以我附加了几个字节到 read 协议,并启动了 WinDbg 看看崩溃是不是和无效数据有关。这些东西迅速且简单,没有 fuzzing 或任何特殊的东西:read:xncbmx,qwieiwqeiu;asjdiw!@#$%^&*

Oh yes,我真的打出来了这些东西。我发现的不会使 read 协议崩溃的唯一方法就是加载来自 http[s]的东西。其他的都会使浏览器崩溃。

那么让我们将 WinDbg 附加至 Edge 浏览器吧。有一个快速的脏方法,我使用它来简单地杀死 Edge 进程和子进程,重新打开它并附加到使用 EdgeHtml.dll 的最新进程。当然还有更简单的方法,但是...yeah,我就是这么做的。打开命令行,然后...

taskkill /f /t /im MicrosoftEdge.exe** Open Edge and load the webpage but make sure it doesn't crash yet **tasklist /m EdgeHtml.dll  

足够了。现在加载 WinDbg ,并将其附加到使用 EdgeHtml 的最新列出的 Edge 进程。记住在 WinDbg 中使用的符合。

一旦附加上去,只需要按 F5 或者在 WinDbg 中按 g [回车],使 Edge 保持运行。这是我屏幕现在看起来的样子。左边有我用来测试一切的页面,在右边, WinDbg 附加到特定的 Edge 进程。

我们将使用 window.open 伴以 read: 协议继续玩耍,而不是一个 iframe ,因为它使用起来更舒服。仔细想想,有的协议/url 可能会最终改变顶部 location,无论它们如何使用框架。

如果我们开始在 iframe 中使用协议,有可能我们自己的页面(顶部)将被卸载,失去我们刚刚键入的代码。我特定的测试页面保存了我键入的内容,如果浏览器崩溃,它很可能被恢复。但即使一切都保存下来了,当我编写一些可以改变我测试页面的 URL 的代码时,我就在一个新窗口中打开它。这只是一种习惯罢了。

在左侧屏幕上,我们可以快速键入并执行 JavaScript 代码,右侧我们有 WinDbg 准备向我们解释在崩溃的背后发生了什么。继续,我们允许 JavaScript 代码以及... Bang! WinDbg 中断了连接。

ModLoad: ce960000 ce996000 C:\Windows\SYSTEM32\XmlLite.dll  
ModLoad: c4110000 c4161000 C:\Windows\System32\OneCoreCommonProxyStub.dll  
ModLoad: d6a20000 d6ab8000 C:\Windows\SYSTEM32\sxs.dll(2c90.33f0): Security check failure or stack buffer overrun - code c0000409 (!!! second chance !!!)EdgeContent!wil::details::ReportFailure+0x120:  84347de0 cd29 int 29h

OK,看来 Edge 知道出了问题因为它位于一个叫做 “ReportFailure” 的函数中,对吧?得了,我知道我们马上可以猜测,如果 Edge 在此,它会有失“优雅”。所以我们检查 stack trace 来看看我们来自何方。在 WinDbg 中输入 “k” 键。

0:030> k  # Child-SP RetAddr Call Site00 af248b30 88087f80 EdgeContent!wil::details::ReportFailure+0x120  01 af24a070 880659a5 EdgeContent!wil::details::ReportFailure_Hr+0x44  02 af24a0d0 8810695c EdgeContent!wil::details::in1diag3::FailFast_Hr+0x29  03 af24a120 88101bcb EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x7c  04 af24a170 880da669 EdgeContent!CReadingModeViewer::Load+0x6b  05 af24a1b0 880da5ab EdgeContent!CBrowserTab::_ReadingModeViewerLoadViaPersistMoniker+0x85  06 af24a200 880da882 EdgeContent!CBrowserTab::_ReadingModeViewerLoad+0x3f  07 af24a240 880da278 EdgeContent!CBrowserTab::_ShowReadingModeViewer+0xb2  08 af24a280 88079a9e EdgeContent!CBrowserTab::_EnterReadingMode+0x224  09 af24a320 d9e4b1d9 EdgeContent!BrowserTelemetry::Instance::2::dynamic  
0a af24a3c0 8810053e shlwapi!IUnknown_Exec+0x79  0b af24a440 880fee33 EdgeContent!CReadingModeController::_NavigateToUrl+0x52  0c af24a4a0 88074f98 EdgeContent!CReadingModeController::Open+0x1d3  0d af24a500 b07df508 EdgeContent!BrowserTelemetry::Instance'::2::dynamic  
0e af24a5d0 b0768c47 edgehtml!FireEvent_BeforeNavigate+0x118  

看看前两行,都叫做 blah blah ReportFailure ,你不觉得 Edge 运行到这里是因为出现错误了吗?当然!让我们继续运行下去,直到我们找到一个有意义的函数名。下一个叫做 blah FallFast,它也有一些 Edge 知道出错了才调用的味道。但是我们想找到使 Edge 不愉悦的代码,那么继续读下去吧。

下一个是 blah _loadRMHTML。这个对我来说看起来好多了,你难道不也这么认为吗?事实上,他的名字让我觉得它是加载 HTML 的。在崩溃之前断下程序的话,这将会变得有意思多了,所以为什么不在 _LoadRMHTML 上面几行设置断点呢?我们检查了 stack-trace,现在我们来看看代码。

我们先从那个断点(函数+偏移)查看反汇编。这很简单,在 WinDbg 中使用 “ub” 命令。

0:030> ub EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x7c  EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x5a:  8810693a call qword ptr [EdgeContent!_imp_SHCreateStreamOnFileEx (882562a8)]  88106940 test eax,eax  88106942 jns EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x7d (8810695d)  88106944 mov rcx,qword ptr [rbp+18h]  88106948 lea r8,[EdgeContent!`string (88261320)]  8810694f mov r9d,eax  88106952 mov edx,1Fh  88106957 call EdgeContent!wil::details::in1diag3::FailFast_Hr (8806597c)

我们将只关注名字,忽略其他东西,好伐?就像我们试着寻找 mimeType bug 的偏差一样,我们在此投机取巧,当然如果我们失败了我们会继续深入。但有时在调试器上的快速查看可以阐明很多事情。

我们知道如果 Edge 到达这个片段的最后一条指令(地址为 88106957,FailFast_Hr),Edge 就会崩溃掉。我们的目标是弄清我们最终到达的地方,就是说谁TM把我带到那里的。上面的代码的第一条指令似乎是调用了一个复杂名称的函数,这显然大量体现了我们的东西。

EdgeContent!_imp_SHCreateStreamOnFileEx

在 ! 前的第一部分是该指令所在的模块(exe,dll等等...)。这种情况下是 EdgeContent 我们甚至不关心它的扩展,它只是一段代码。! 之后有个有趣的函数名叫_imp_ ,然后 SHCreateStreamOnFileEx 似乎是一个“创建文件流”的函数名。你同意吗?事实上,_imp_的部分让我想起这可能是从不同的二进制文件加载的导入函数。让我 google 一下这个名字,看看能不能找到有趣的东西。

这太棒了。第一个结果正是我们搜索的准确名称。让我们点击一下。

好。此函数接收的第一个参数是 “A pointer to a null-terminated string that specifies the file name” 。因垂丝挺!如果这段代码正被执行,,那么它应该接收一个指向文件名的指针作为第一个参数。但是我们这么能看到第一个参数呢?很简单,我们在 Win x64上运行,调用约定/参数解析说,“前四个参数是 RCX, RDX, R8, R9 ”(说道整数/指针)。这意味着第一个参数(指向文件名的指针)将被装载入 RCX 寄存器。

有了这些信息,我们可以在 Edge 调用之前设置一个断点,看看 RCX 在那个确定时刻有何值。但是我们重新启动一遍程序吧,因为这时已经有点迟了:Edge 已经崩溃了。请重新按照上面描述的做一遍(杀掉 Edge 进程,打开它,加载页面,找到进程并附加上去)。

这个时候,不要运行(F5)进程,我们先设置一个断点。WinDbg 显示了我们执行 “ub” 命令时的确切偏移量。

0:030> ub EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x7c  EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x5a:  8810693a ff1568f91400 call qword ptr [EdgeContent!_imp_SHCreateStreamOnFileEx (882562a8)]  88106940 85c0 test eax,eax  

所以断点应该在 EdgeContent!CReadingModeViewerEdge :: _ LoadRMHTML 0x5a 处。我们键入 “bp” 和函数名 + 偏移[回车]。然后 “g” 让 Edge 运行。

0:029> bp EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x5a  
0:029> g  

这很一颗赛艇。在 SHCreateStreamOnFileEx 执行之前,我们想要看到 RCX 指向的文件名(或者字符串)。我们运行代码,稍适小憩。好吧,宝宝我感受到它了 =) 断点连至我的童年。让我们运行这段 JavaScript 代码吧,bang!WinDbg 在此中断。

Breakpoint 0 hit  
EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x5a:  8820693a ff1568f91400 call qword ptr [EdgeContent!_imp_SHCreateStreamOnFileEx (883562a8)]

这太棒了,现在我们可以检查 RCX 指向的内容。为此我们使用 “d” 命令(显示内存)@ 和寄存器名称,如下所示:

0:030> d @rcx  
02fac908 71 00 77 00 69 00 65 00-69 00 77 00 71 00 65 00 q.w.i.e.i.w.q.e.  
02fac918 69 00 75 00 3b 00 61 00-73 00 6a 00 64 00 69 00 i.u.;.a.s.j.d.i.  
02fac928 77 00 21 00 40 00 23 00-24 00 25 00 5e 00 26 00 w.!.@.#.$.%.^.&.  
02fac938 2a 00 00 00 00 00 08 00-60 9e f8 02 db 01 00 00 *.......`.......  
02fac948 10 a9 70 02 db 01 00 00-01 00 00 00 00 00 00 00 ..p.............  
02fac958 05 00 00 00 00 00 00 00-00 00 00 00 19 6c 01 00 .............l..  
02fac968 44 14 00 37 62 de 77 46-9d 68 27 f3 e0 92 00 00 D..7b.wF.h'.....  
02fac978 00 00 00 00 00 00 08 00-00 00 00 00 00 00 00 00 ................  

这对我的眼睛很不好,但在第一行的右边,我看到了一些类似于 Unicode 字符串的东西。我们将它显示为Unicode字符吧(du)。

0:030> du @rcx  
02fac908 "qwieiwqeiu;asjdiw!@#$%^&*"  

Nice!字符串将我包围!看看我们刚才运行的 JavaScript 代码。

看来,传给这个函数的参数是逗号后面输入的任何内容。有了这点知识加上知道它期望是一个文件,我们可以尝试一个在硬盘上的完整的路径。因为 Edge 在 AppContainer 内部运行,我们将尝试一个可访问的文件。例如来自 windows/system32 目录的内容。

read:,c:\windows\system32\drivers\etc\hosts  

我们也在删除逗号之前的垃圾,看起来似乎无关(虽然他值得进行更多研究)。我们快速分离,重启 Edge,并运行我们的新代码。

url = "read:,c:\\windows\\system32\\drivers\\etc\\hosts";w = window.open(url, "", "width=300,height=300");  

正如预期,在新窗口中加载本地文件并没有崩溃。

[ PoC – Open hosts on MS Edge ]

跟着 bug hunter,我将在此停顿,但我详细所有的这些事情值得更多的研究,取决于你获得的乐趣了:

A)枚举所有可加载的协议,并通过请求字符串攻击应用程序

B) 使用 microsoft-edge: 绕过 HTML5 沙盒,弹出窗口拦截器和不知谁知道的东西。

C) 继续使用 read: 协议。我们找到了一种方法来阻止它崩溃,但记住有一个函数 SHCreateStreamOnFileEx 期望我们能够影响的东西!这值得更多尝试。此外,我们可以继续在参数上做点事情,看看是否使用逗号分隔参数等等。如果调试二进制是无聊的,那么你仍然可以尝试对阅读视图进行 XSS。

希望你能找到成吨的漏洞!如果你有问题,请在@magicmac2000 上 ping 我。

Have a nice day!

Reported to MSRC on 2016-10-26

原文发布于微信公众号 - Seebug漏洞平台(seebug_org)

原文发表时间:2016-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

Java和Python的Web开发

在Java里面有一种服务端的软件组件技术,叫做Servlet,其实它的定位就是轻巧的小玩意,比如Java里面的applet也是类似的命名。Servlet能够动态...

33340
来自专栏小怪聊职场

HTTP|GET 和 POST 区别?网上多数答案都是错的!

375100
来自专栏从零开始学自动化测试

selenium+python自动化81-报告优化

一、 优化html报告 为了满足小伙伴的各种变态需求,为了装逼提示逼格,为了让报告更加高大上,测试报告做了以下优化: - 测试报告中文显示,优化一些断言失败...

47750
来自专栏坚毅的PHP

node.js进阶学习

简介 如果您听说过 Node,或者阅读过一些文章,宣称 Node 是多么多么的棒,那么您可能会想:“Node 究竟是什么东西?”尽管不是针对所有人的,但 Nod...

46970
来自专栏Golang语言社区

[Go语言]一种用于网游服务器的支持多路复用的网络协议处理框架

简介: 本文描述了使用Go语言实现的、适应于Go语言并发模型的一种支持多路复用的网络协议处理框架,并提供了框架的代码实现。作者将这种框架用于网络游戏服务器中的协...

34660
来自专栏CSDN技术头条

调试大规模服务器集群的五大策略

随着互联网迅速发展,用户访问量以及服务器规模的越来越大,因此,创建一个可靠、稳定、优质的互联网服务是开发者的首要目标。而对于开发者而言,是否具备一个完善的服务器...

28590
来自专栏向治洪

android mtp简介

经作者同意,转发我们公司MTP专家同事huirong的一篇文章。大家也可在程序员第5期看到。 MTP in Android MTP的全称是Media Tra...

50260
来自专栏Java后端技术栈

为什么说Redis是单线程的?

近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”、什么是“热数据和冷数据” ,复杂一点的会问到缓存雪崩、缓存穿透、缓存预热、缓...

17620
来自专栏腾讯大数据的专栏

大型web系统数据缓存设计

1. 前言 在高访问量的web系统中,缓存几乎是离不开的;但是一个适当、高效的缓存方案设计却并不容易;所以接下来将讨论一下应用系统缓存的设计方面应该注意哪些...

53860
来自专栏CSDN技术头条

缓存那些事

导语:在网络分层应用服务中,缓存的使用已比较普及,本文将结合作者实际工作经验总结,讲述在不同的场景下如何选择和使用适用的缓存框架,以达到提升服务质量,优化系统...

28070

扫码关注云+社区

领取腾讯云代金券