前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用特殊协议加载本地文件, 绕过 HTML5 沙箱, 打开弹窗诸事

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

作者头像
Seebug漏洞平台
发布2018-03-30 10:08:03
2.3K0
发布2018-03-30 10:08:03
举报
文章被收录于专栏:Seebug漏洞平台Seebug漏洞平台

原文链接: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 (甚至不打开新标签),我们只需要使用此标签:

代码语言: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,我就是这么做的。打开命令行,然后...

代码语言:javascript
复制
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 中断了连接。

代码语言:javascript
复制
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” 键。

代码语言:javascript
复制
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” 命令。

代码语言:javascript
复制
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” 命令时的确切偏移量。

代码语言:javascript
复制
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 运行。

代码语言:javascript
复制
0:029> bp EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x5a  
0:029> g  

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

代码语言:javascript
复制
Breakpoint 0 hit  
EdgeContent!CReadingModeViewerEdge::_LoadRMHTML+0x5a:  8820693a ff1568f91400 call qword ptr [EdgeContent!_imp_SHCreateStreamOnFileEx (883562a8)]

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

代码语言:javascript
复制
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)。

代码语言:javascript
复制
0:030> du @rcx  
02fac908 "qwieiwqeiu;asjdiw!@#$%^&*"  

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

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

代码语言:javascript
复制
read:,c:\windows\system32\drivers\etc\hosts  

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

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Seebug漏洞平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [ PoC – 在微软 Edge 浏览器上弹窗 ]
  • [ PoC – 在 微软 Edge 浏览器上绕过 HTML5 沙箱 ]
  • [ PoC – Crash on MS Edge ]
  • [ PoC – Open hosts on MS Edge ]
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档