前言
之前打 GeekGame 的时候就遇到过利用 chrome 扩展进行 xss 的题,正好看到有相关的文章,遂学习一下
参考:
https://blog.xlab.app/p/4db211d1/
https://blog.xlab.app/p/4db211d2/
基础知识
组件介绍
edge 的扩展位置在 %localappdata%\Microsoft\Edge\User Data\Default\Extensions
接下来以 GeekGame2024 里 web-crx 更新后的扩展文件 bxx 为例子来熟悉组件
manifest.json
官方文档:https://developer.chrome.google.cn/docs/extensions/reference/manifest?hl=zh-cn
扩展程序的配置清单,放在扩展程序代码的根目录,包含以下内容:
名称,描述,版本等
最小清单:
{ "manifest_version": 3, "name": "Minimal Manifest", "version": "1.0.0", "description": "A basic example extension with only required keys", "icons": { "48": "images/icon-48.png", "128": "images/icon-128.png" }, }
API权限定义,如 读写书签/历史/Cookie 等 Chrome API
"permissions": ["tabs", "scripting"]
网站权限定义,允许无视同源策略访问哪些网站
"host_permissions": [ "<all_urls>" ]
定义
Content scripts
是哪些 js,在哪里何时运行等"content_scripts": [ { "matches": ["*://*/*"], "js": ["contentScript.bundle.js"] } ]
定义
Background scripts
是哪些 js"background": { "service_worker": "background.bundle.js" }
CSP
策略…
Content scripts
https://developer.chrome.google.cn/docs/extensions/reference/manifest/content-scripts?hl=zh-cn
在每个标签页中运行,每个扩展一个隔离环境,有独立的JavaScript
变量,CSP
策略等,同时拥有一部分Chrome API功能,只与网页中的JS使用同一个DOM
一般用来处理与网页DOM
相关的功能,或与Background scripts
通信交互完成相关功能
同源策略与所在的标签页相同
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["contentScript.bundle.js"]
}
]
- matches:将内容脚本注入到的网址格式,这里匹配所有的网址
- js:注入网页的 js 脚本
Inject scripts
由于Content scripts
与网页隔离,有些功能又需要访问网页空间中的数据
那么扩展程序往往会在Content scripts
中通过DOM
注入各种标签,当然也包括script
这里是在 contentScript.bundle.js 里面进行插入的
var style = document.createElement('style');
style.textContent = styles;
document.head.append(style);
如果插入的是 script 标签便会引入一些攻击面
Background scripts
扩展程序的后台服务,拥有完整的Chrome API功能,但不能直接访问DOM
一般用于持续运行的功能,或依赖相关Chrome API的功能
在一定的权限设定下,无同源策略限制
在Manifest V2中是一个HTML,叫background.html
,如果是JS的话会自动生成一个HTML
在Manifest V3中是一个JS,叫Service Worker
"background": {
"service_worker": "background.bundle.js"
}
background.bundle.js 里对应的代码
chrome.runtime.onInstalled.addListener((function(t){
"install"===t.reason && chrome.tabs.create({url: "chrome://newtab"})
}));
监听安装行为,在安装此扩展时在浏览器打开一个新标签页
Popup
定义的位置在 action 的 default_popup
是点击扩展图标后弹出的页面,权限与Background
组件相同
以 沉浸式翻译 为例子:
"action": {
"default_icon": {
"128": "icons/128.png",
"256": "icons/256.png",
"32": "icons/32.png",
"48": "icons/48.png",
"64": "icons/64.png"
},
"default_popup": "popup.html"
}
options_page
为扩展的选项页,权限与Background
组件相同
通信架构
Webpage 是指网页 Javascript 的空间,与 Content 共享 DOM,其中 window 比较特殊,虽然是共用一个 window,但有变量隔离
由于共用 window ,Webpage 与 Content 可以使用window.postMessage
进行通信
当 Content 调用chrome.runtime.sendMessage
时其实在向所有 Background 页面中广播
同理,Background 页面之间使用chrome.runtime.sendMessage
发送消息时也相当于在广播
漏洞分析
前端漏洞主要还是围绕 XSS 和 CSRF
而 Chrome Manifest V3 中规定禁止代码执行,禁止加载远程资源,体现在CSP中无法添加unsafe-eval
和unsafe-inline
,也无法添加任何远程地址,导致想要在 Manifest V3 实现 XSS 非常困难
Content scripts
DOM
由于 Content scripts 与网页 JS 共享DOM
对于攻击者来说,攻击入口包括整个 DOM
DOM Event
除了Content
去直接查询DOM
元素,还有订阅事件
onmessage
由于Content scripts
与网页使用同一个window
,postMessage
将直接与Content scripts
通信
如果没有校验来源,甚至可以利用 iframe 或者 window.open 获取目标window,跨域发送消息直达Content scripts
完成攻击
window.name
虽然说Content
与网页隔离,变量不能共享,但是window.name
是个例外
Web Storage
如果在Content
中使用Web Storage,其实是在使用当前网站的存储,而不是扩展程序自己的
写入Web Storage存在信息泄露,同时读取Web Storage也是用户输入