开卷有益 · 不求甚解
在上一篇文章中,我们讨论了扩展权限。正如我们从另一篇文章中了解到的,扩展页面是具有这些权限的完全访问权限的扩展上下文。因此,如果有人要攻击浏览器扩展,在扩展页面中尝试远程代码执行 (RCE) 将是显而易见的事情。
在本文中,我们将对示例扩展进行一些更改,以使针对它的攻击变得可行。但不要误会:由于浏览器实施的安全措施,使我们的扩展易受攻击需要实际工作。
这并不意味着此类攻击对现实世界的扩展永远不可行。有时,即使是这些高效的机制也无法防止灾难性的漏洞。当然,还有一些扩展明确禁用了安全机制,带来了类似的灾难性结果。具有讽刺意味的是,这两个示例都被认为是由大型防病毒供应商创建的安全产品。
注意:本文是浏览器扩展安全基础知识系列的一部分。它旨在为您提供对该领域的一些了解,并作为我更具体文章的参考。您可以浏览extension-security-basics 类别以查看本系列中其他已发布的文章。
扩展页面只是普通的 HTML 页面。所以我们这里所说的远程代码执行,在其他情况下通常被称为跨站脚本(XSS)漏洞。仅此类漏洞的影响通常对浏览器扩展更为严重。
一个经典的 XSS 漏洞将涉及不安全地处理不受信任的 HTML 代码:
var div = document.createElement("div");
div.innerHTML = untrustedData;
document.body.appendChild(div);
如果攻击者可以决定在innerHTML
这里分配什么样的数据,他们可以选择像<img src="x" onerror="alert('XSS')">
. 一旦该图像被添加到文档中,浏览器将尝试加载它。加载失败,触发error
事件处理程序。该处理程序是内联定义的,这意味着 JavaScript 代码alert('XSS')
将运行。因此,您会收到一条指示成功利用的消息:
这是您的第一个障碍:典型的攻击目标是背景页面,这要归功于它对于大多数浏览器扩展的重要性。然而背景页面是不可见的,这意味着它没有理由处理 HTML 代码。
那么直接执行不受信任代码的页面呢?类似于以下内容:
eval(untrustedData);
乍一看,这似乎不太可能。实际上没有开发人员会这样做,对吗?
实际上,如果他们使用对运行 JavaScript 代码具有亲和力的 jQuery作为意外的副作用,他们就会这样做。
我将一一讨论对示例扩展的所有更改。但是您可以在此处下载带有完整扩展源代码的 ZIP 文件。
在扩展页面可以运行恶意代码之前,该代码必须来自某个地方。然而,网站,无论是否恶意,通常不能直接访问扩展页面。所以他们必须依靠扩展内容脚本来传递恶意数据。这种关注点分离大大减少了攻击面。
但是假设我们的扩展想要显示当前查看的商品的价格。问题:内容脚本无法下载带有价格的 JSON 文件。这是因为内容脚本本身运行在www.example.com
JSON 文件存储在 上data.example.com
,因此同源策略生效。
没问题,内容脚本可以要求后台页面下载数据:
chrome.runtime.sendMessage({
type: "check_price",
url: location.href.replace("www.", "data.") + ".json"
}, response => alert("The price is: " + response));
下一步:后台页面需要处理这个消息。扩展开发人员可能会认为fetch API过于复杂,这就是他们宁愿使用jQuery.ajax()的原因。所以他们做了以下事情:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request.type == "check_price")
{
$.get(request.url).done(data =>
{
sendResponse(data.price);
});
return true;
}
});
看起来很简单。该扩展需要加载最新的 jQuery 2.x 库作为后台脚本并请求访问权限data.example.com
,这意味着以下更改manifest.json
:
{
…
"permissions": [
"storage",
"https://data.example.com/*"
],
…
"background": {
"scripts": [
"jquery-2.2.4.min.js",
"background.js"
]
},
…
}
这似乎工作正常。当内容脚本执行时,https://www.example.com/my-item
它会要求后台页面下载https://data.example.com/my-item.json
。后台页面遵从、解析 JSON 数据、获取price
字段并将其发送回内容脚本。
您可能想知道:我们在哪里告诉 jQuery 解析 JSON 数据?而我们实际上没有。jQuery 只是猜测我们希望它解析 JSON,因为我们下载了一个 JSON 文件。
如果https://data.example.com/my-item.json
不是 JSON 文件会怎样?然后 jQuery 可能会将此数据解释为它支持的任何一种数据类型。默认情况下,它们是:xml
、或。您可能已经发现了问题:类型不安全。json``script``html``script
因此,如果一个网站想要利用我们的扩展,最简单的方法是application/javascript
在https://data.example.com/my-item.json
. 例如,可以使用以下代码:
alert("Running in the extension!");
然后 jQuery 会尝试在后台页面中运行该脚本吗?你打赌!
但是浏览器再次拯救了这一天。开发者工具现在为后台页面显示以下问题:
注意:我没有使用 jQuery 3.x 是有原因的。开发人员最终解决了跨域请求的这种危险行为。在 jQuery 4.x 中,它甚至会被所有请求禁用。尽管如此,jQuery 2.x 甚至 1.x 在浏览器扩展中仍然太常见了。
阻止这种攻击的内容安全策略(CSP)机制非常有效。浏览器扩展页面的默认设置相当严格:
script-src 'self'; object-src 'self';
此处的script-src
条目决定了扩展页面可以运行哪些脚本。'self'
意味着只允许包含在扩展本身中的脚本。再多的诡计都不会使此扩展程序在扩展程序页面上运行恶意脚本。这种保护使所有漏洞都无法利用,或者至少大大降低了它们的严重性。好吧,几乎所有的漏洞。
除非扩展放松了这种保护,这太常见了。例如,一些扩展会在其manifest.json
文件中显式更改此设置以允许eval()
调用:
{
…
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';",
…
}
保护消失了,上面描述的攻击突然起作用了!
我听到你喃喃“作弊”了吗?“没有真正的扩展会那样做”你说?我不敢苟同。在我的扩展调查中,7.9% 的扩展使用'unsafe-eval'
放松默认的内容安全策略设置。
事实上:更流行的扩展更有可能是这里的违规者。在查看拥有超过 10,000 个用户的扩展程序时,它已经是其中的 12.5%。对于至少拥有 100,000 名用户的扩展程序,这一份额上升到 15.4%。
编辑(2022-08-24):本节最初提到'unsafe-inline'
脚本来源。但是,浏览器扩展会忽略它,因此它在此上下文中实际上并不相关。
它并不总是必须是'unsafe-eval'
基本上放弃所有防御的脚本源。有时它更无害,例如将某个网站添加为受信任的脚本源:
{
…
"content_security_policy": "script-src 'self' https://example.com/;"
…
}
作为example.com
一些大牌的代码托管,甚至是扩展所有者自己的网站,它当然可以信任?有人入侵该服务器只是为了在扩展程序中运行一些恶意脚本的可能性有多大?
实际上,入侵服务器通常是没有必要的。偶尔example.com
会包含一个JSONP 端点或类似的东西。例如,https://example.com/get_data?callback=ready
可能会产生如下响应:
ready({...some data here...});
攻击者将尝试操纵此回调名称,例如加载https://example.com/get_data?callback=alert("XSS")//
将导致以下脚本:
alert("XSS")//({...some data here...});
就是这样,现在example.com
可以用来生成带有任意代码的脚本并且CSP保护不再有效。
旁注:如今,JSONP 端点通常将回调名称限制为仅限字母数字字符,以防止这种滥用。然而,没有这种保护的 JSONP 端点仍然太常见了。
编辑(2022-08-25):本文的原始版本提到开放重定向是另一种 CSP 规避方法。但是,当前浏览器版本也会根据 CSP 检查重定向目标。
因此,如果您是扩展开发人员,并且想要保护您的扩展免受此类攻击,您可以做什么?
首先也是最重要的:让内容安全策略保护您。避免'unsafe-eval'
不惜一切代价添加。与其允许外部脚本源,不如将这些脚本与您的扩展捆绑在一起。如果您绝对无法避免加载外部脚本,请尽量保持列表简短。
然后是防止 XSS 漏洞的通常建议:
https://
或至少http://
以使任何人都无法偷运链接开头javascript:
。近期阅读文章
,质量尚可的,大部分较新,但也可能有老文章。开卷有益,不求甚解
,不需面面俱到,能学到一个小技巧就赚了。译文仅供参考
,具体内容表达以及含义, 以原文为准
(译文来自自动翻译)尽量阅读原文
。(点击原文跳转)每日早读
基本自动化发布(不定期删除),这是一项测试
最新动态: Follow Me
微信/微博:
red4blue
公众号/知乎:
blueteams