关于sandbox相关
用途
- 进程隔离
CEF采多进程架构,主要包括浏览器进程和渲染进程- 沙盒机制将渲染进程与浏览器进程隔离开来,使得即使渲染进程中存在恶意代码或漏洞,也不会直接影响浏览器进程及宿主系统
- 权限限制
- 沙盒限制渲染进程的权限,防止其访问和修改系统的敏感资源,如文件系统、注册表、网络和设备等
- 渲染进程只能访问被允许的资源,从而降低潜在的安全风险
- 防止漏洞利用
- 通过沙盒机制,可以有效防止攻击者利用渲染进程中的漏洞执行特权操作或提升权限
- 即使存在零日漏洞,攻击者也难以突破沙盒的限制,进一步攻击系统
- 数据保护
- 沙盒机制保护用户数据,防止渲染进程未经授权访问和泄露用户敏感信息
- 浏览器中的每个标签页和插件运行在独立的沙盒中,隔离彼此的数据访问
技术
-
CEF中的沙盒机制依赖于Chromium的沙盒架构,主要通过以下几个关键技术实现: -
多进程架构:
CEF使用多进程模型,将不同的浏览器组件运行在独立的进程中- 主要包括浏览器进程、渲染进程、
GPU进程、插件进程等 - 每个进程具有不同的职责和权限
-
操作系统级别的沙盒:
CEF依赖操作系统提供的沙盒机制- 如
Windows上的Job Object、Token、Integrity Level,Linux上的Namespace和Seccomp,macOS上的Seatbelt等 - 通过操作系统提供的安全功能,对渲染进程的权限进行细粒度控制
-
进程间通信:
- 多进程架构需要各进程之间进行通信
CEF使用Chromium的IPC机制实现进程间的消息传递和数据交换- 通过
IPC,浏览器进程与渲染进程可以安全地协同工作,同时确保渲染进程的沙盒隔离
-
权限模型:
- 每个进程根据其角色和功能分配不同的权限
- 渲染进程的权限最小化,仅限于渲染和执行
JavaScript代码,不允许直接访问系统资源 - 浏览器进程则拥有更多的权限,负责管理和协调各个子进程的工作
-
安全策略:
CEF实现了一系列安全策略,如内容安全策略(CSP)、跨域策略、同源策略等,限制渲染进程的行为和资源访问,防止恶意代码绕过沙盒机制
细节
- 后续研究源码实现
目标进程
- 渲染进程
- 渲染进程是主要的沙盒目标,因为它直接处理和执行来自网络的内容,包括
HTML、CSS和JavaScript - 渲染进程的权限被大幅度削减,通常不能直接访问文件系统、网络或设备
- 每个浏览器标签页或框架可能运行在单独的渲染进程中,确保即使一个标签页被攻破,其他标签页和系统依然安全
- 渲染进程是主要的沙盒目标,因为它直接处理和执行来自网络的内容,包括
- 插件进程
- 插件进程用于运行浏览器插件,如
Flash或其他类型的内容插件
由于插件可能包含漏洞,也需要在沙盒中运行 - 每个插件运行在独立的沙盒进程中,防止其对浏览器和系统造成影响
- 限制插件进程的权限,确保它们只能访问必要的资源
- 插件进程用于运行浏览器插件,如
GPU进程GPU进程处理与图形渲染相关的任务
虽然GPU进程的沙盒限制通常不如渲染进程严格,但仍然需要一些限制以防止潜在的攻击GPU进程在沙盒中运行,防止其对其他进程和系统资源的非法访问
- 网络进程
- 网络进程负责处理网络请求和数据传输
- 网络进程在沙盒中运行,确保即使网络数据包含恶意内容,也不会直接威胁系统安全
理解
- 就是现代操作系统提供了一些内置的机制和功能,用于实现进程隔离和权限限制,即沙盒能力
- 在
CEF或Chromium中,启用或禁用沙盒实际上是通过配置和设置来告诉操作系统,是否应对特定的子进程应用操作系统的沙盒能力
操作系统的沙盒机制
Windows
- 使用
Job Objects限制进程的资源使用 - 使用
Integrity Levels将进程置于低权限环境中 - 使用
AppContainer将进程隔离
Linux
- 使用
Namespaces隔离进程的文件系统、网络等资源 - 使用
Seccomp限制系统调用
macOS
- 使用
Seatbelt Profiles定义进程可以访问的资源和权限
关于wrap相关
cef导出的是c风格的API,在wrap这一层这里,对这些api进行了封装,接入了cef的应用程序要使用cef的功能的话,只需要调用wrap里面封装好的函数和类- 这样做的作用
wrap层封装了C API。提供了一套C++风格的API,使开发者能更方便使用CEF的功能- 这层封装通常包括了对浏览器进程、渲染进程、
V8引擎等核心功能的C++类和方法,使得开发者可以更直观和高效地编写代码
CefApp详解
概述
- 负责管理
CEF应用程序的整个生命周期- 在应用程序启动和结束的不同阶段,
CefApp类会触发相应的回调方法,供开发者处理相关的逻辑
- 在应用程序启动和结束的不同阶段,
- 在应用程序启动阶段,开发者可以通过继承
CefApp类并重写其中的方法,来进行初始化和配置 - 负责管理
CEF的进程,包括浏览器进程、渲染进程、插件进程等- 通过重写
CefApp的方法,可以对不同类型的进程进行定制化的管理
- 通过重写
- 通过继承
CefApp类并重写其中的方法,开发者可以实现自定义的功能 - 负责管理
CEF应用程序所需的资源,包括内存、文件、图片等- 通过
CefApp类的方法,可以实现资源的加载、释放和管理
- 通过
- 与操作系统进行交互,处理操作系统相关的事件和消息
- 例如,可以通过重写
CefApp的方法来处理操作系统的窗口消息、键盘事件等
- 例如,可以通过重写
- 在多进程的架构下,
CefApp类负责协调不同进程之间的通信和协作- 通过重写
CefApp的方法,可以实现进程之间的消息传递和数据共享
- 通过重写
OnBeforeCommandLineProcessing
- 提供在
CEF和Chromium处理之前查看或修改命令行参数的机会 - 对于浏览器进程,
process_type值将为空 - 不要保留传递给此方法的
CefCommandLine对象的引用 cef_settings_t.command_line_args_disabled值可用于以空的命令行对象开始- 在调用此方法之前,将设置
CefSettings中指定的任何等同于命令行参数的值
- 在调用此方法之前,将设置
- 使用此方法修改非浏览器进程的命令行参数时要小心,因为这可能会导致未定义的行为,包括崩溃。
OnRegisterCustomSchemes
- 提供注册自定义方案的机会
- (自定义方案)是一种允许开发者注册自定义协议方案的机制
这种机制允许开发者通过自定义的协议来访问和处理特定类型的资源,而不局限于常见的HTTP、HTTPS等协议 - 通过自定义方案,开发者可以访问本地文件系统中的资源,而不需要通过
HTTP或其他网络协议 - 开发者可以通过自定义方案来加载自定义的资源,例如内存中的数据、应用程序中的特定文件等
- 自定义方案可以用于实现特定功能,例如访问特定硬件设备、与其他应用程序进行通信等
- (自定义方案)是一种允许开发者注册自定义协议方案的机制
- 不要保留对
registrar对象的引用- 此方法在每个进程的主线程上调用,并且注册的方案在所有进程中应该相同
- 在
CEF中,要实现Custom Schemes:- 通过
CefSchemeRegistrar::AddCustomScheme方法注册自定义方案
这个过程通常在CefApp类的OnRegisterCustomSchemes方法中完成 - 通过
CefResourceHandler类的派生类来处理对自定义方案的请求
这个过程通常在自定义的CefApp类中实现
- 通过
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class CustomApp : public CefApp { public: // 注册自定义方案 virtual void OnRegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar) override { registrar->AddCustomScheme("custom", true, false, false); } }; class CustomResourceHandler : public CefResourceHandler { // 实现资源加载逻辑... }; int main() { // 初始化 CEF CefMainArgs main_args; CefRefPtr<CustomApp> app(new CustomApp()); CefInitialize(main_args, app, NULL); // 注册自定义资源处理器 CefRegisterSchemeHandlerFactory("custom", "", new CustomResourceHandlerFactory()); // 启动 CEF 消息循环 CefRunMessageLoop(); // 关闭 CEF CefShutdown(); return 0; } |
GetResourceBundleHandler
- 返回资源包事件的处理程序
- 如果
cef_settings_t.pack_loading_disabled为true,则必须返回处理程序
如果没有返回处理程序,资源将从包文件加载 - 此方法由浏览器和渲染进程在多个线程上调用
- 如果
GetBrowserProcessHandler
- 返回浏览器进程特定功能的处理程序
- 此方法在浏览器进程中的多个线程上调用
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
class MyApp : public CefApp { public: virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override { return this; } // 实现浏览器进程的生命周期事件处理方法 virtual void OnContextInitialized() override { // 在浏览器进程初始化完成后进行初始化操作 // 例如注册自定义方案、加载资源等 } virtual void OnBeforeChildProcessLaunch(CefRefPtr<CefCommandLine> command_line) override { // 在子进程启动前进行一些额外的设置 // 例如传递特定的命令行参数等 } virtual void OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info) override { // 在渲染进程线程创建时进行处理 // 例如设置渲染进程的一些属性 } virtual void OnScheduleMessagePumpWork(int64 delay_ms) override { // 在消息泵中安排一些额外的工作 // 例如处理异步任务、更新UI等 } }; |
GetRenderProcessHandler
- 返回渲染进程特定功能的处理程序
- 此方法在渲染进程主线程上调用
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class CustomApp : public CefApp { public: // 返回渲染进程处理器实例 virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return new CustomRenderProcessHandler(); } }; class CustomRenderProcessHandler : public CefRenderProcessHandler { // 实现渲染进程处理逻辑... }; int main() { // 初始化 CEF CefMainArgs main_args; CefRefPtr<CustomApp> app(new CustomApp()); CefInitialize(main_args, app, NULL); // 启动 CEF 消息循环 CefRunMessageLoop(); // 关闭 CEF CefShutdown(); return 0; } |
CefClient详解
概述
- 负责处理与浏览器相关的各种事件,例如页面加载完成、页面标题变化、页面加载进度更新等
- 可以用于实现浏览器的各种功能,例如自定义右键菜单、处理鼠标事件、处理键盘事件等
- 开发者可以控制浏览器的行为,例如禁用或启用
JavaScript、禁用或启用图片加载、设置浏览器的缓存策略等 - 可以用于自定义浏览器的用户界面(
UI),例如添加自定义工具栏、添加自定义菜单等 - 可以用于处理来自
JavaScript的消息,例如通过JavaScript调用本地代码、在页面中执行特定的JavaScript代码等 - 开发者可以实现自定义的资源加载逻辑,例如加载本地文件、加载内存中的数据、拦截和修改网络请求等
- 提供了扩展浏览器功能的接口,开发者可以根据自己的需求来实现各种定制化的功能,并与浏览器进行交互
GetAudioHandler
- 返回音频渲染事件的处理程序
GetCommandHandler
- 返回命令的处理程序
- 如果没有提供处理程序,则将使用默认实现
GetContextMenuHandler
- 返回上下文菜单的处理程序
- 如果没有提供处理程序,则将使用默认实现
- 上下文菜单通常指的是在浏览器中右键单击时弹出的菜单,也称为右键菜单或上下文菜单
GetDialogHandler
- 返回对话框的处理程序
- 如果没有提供处理程序,则将使用默认实现
GetDisplayHandler
- 返回浏览器显示状态事件的处理程序
GetDownloadHandler
- 返回下载事件的处理程序
- 如果没有返回处理程序则不允许下载
GetDragHandler
- 返回拖动事件的处理程序
GetFindHandler
- 返回查找结果事件的处理程序
GetFocusHandler
- 返回焦点事件的处理程序
GetFrameHandler
- 返回与
CefFrame生命周期相关的事件的处理程序 - 此方法将在
CefBrowser创建期间调用一次,并且出于性能原因,结果将被缓存
GetPermissionHandler
- 返回权限请求的处理程序
GetJSDialogHandler
- 返回
JavaScript对话框的处理程序- 如果没有提供处理程序,则将使用默认实现
GetKeyboardHandler
- 返回键盘事件的处理程序
GetLifeSpanHandler
- 返回浏览器生命周期事件的处理程序
GetLoadHandler
- 返回浏览器加载状态事件的处理程序
GetPrintHandler
- 返回
Linux上打印的处理程序- 如果没有提供打印处理程序,则
Linux平台将不支持打印
- 如果没有提供打印处理程序,则
GetRenderHandler
- 返回屏幕外渲染事件的处理程序
GetRequestHandler
- 返回浏览器请求事件的处理程序
OnProcessMessageReceived
- 当从其他进程收到新消息时调用
- 如果消息已处理,则返回
true,否则返回false
- 如果消息已处理,则返回
- 在此回调之外保留对
message的引用是安全的
View BrowserView Browser
view
View是UI层级结构中的一个基本单元,用于显示和管理用户界面的一部分内容View可以是按钮、标签、文本框、图像等可见的用户界面元素View提供了处理用户输入事件、绘制界面元素、布局管理等功能
BrowserView
BrowserView是用于将Browser内容嵌入到应用程序的UI中的容器BrowserView将Browser的内容显示在应用程序的窗口中,并提供了与Browser交互的界面BrowserView可以视作是一个可以显示Web内容的UI视图
Browser
Browser是一个完整的浏览器实例,用于加载和渲染Web内容,并提供与Web页面交互的功能Browser负责管理一个或多个标签页(Tab),每个标签页对应一个独立的Web页面- 每个
Tab对应一个主框架(Main Frame),如果该Tab内有嵌入的iframe,则还会有多个子框架
- 每个
Browser提供了加载URL、导航、执行JavaScript、管理插件等功能
Frame
Browser是一个完整的浏览器实例,包含一个或多个CefFrame- 主框架是页面的主文档
- 其他框架则对应于嵌入的
iframe
- 每个
CefFrame对应于一个HTML文档或一个iframe- 浏览器中的主文档是一个
CefFrame,每个嵌入的iframe也是一个独立的CefFrame iframe是HTML中的一种元素,用于在一个HTML文档中嵌入另一个HTML文档- 它允许在同一个浏览器窗口中显示多个独立的
HTML页面,每个页面可以来自不同的源
- 浏览器中的主文档是一个
iframe作用:- 可以嵌入来自不同
URL的内容,例如嵌入另一个网站的页面、嵌入广告、嵌入视频播放器等 iframe中的内容与主页面相互隔离,具有独立的上下文环境
这意味着iframe中的JavaScript和CSS不会影响主页面,反之亦然- 通过
iframe,你可以嵌入来自不同域的内容,而不必担心跨域限制
(尽管跨域通信仍然受到限制,需要使用postMessage等方法进行安全的跨域通信)
- 可以嵌入来自不同
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!DOCTYPE html> <html> <head> <title>主页面</title> </head> <body> <h1> test </h1> <iframe src="https://www.test.com" width="600", height="400"> test bbbb </iframe> </body> </html> |
关系
View和BrowserViewBrowserView是一个特化的View,用于浏览器内容显示
BrowserView和BrowserBrowserView包含一个CefBrowser实例,负责将其内容呈现在UI中
Browser和FrameCefBrowser管理主框架和所有子框架(iframe)
关系图示
View:应用程序的用户界面容器BrowserView:显示浏览器内容的视图组件Browser:完整的浏览器实例,管理页面和框架Frame:表示HTML文档或iframe的框架
|
1 2 3 4 5 |
View └── BrowserView └── Browser ├── Frame (Main Frame) └── Frame (Sub Frame) |
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ X86_64汇编学习记述三08/08
- ♥ Linux 高性能服务器编程:服务器程序规范12/04
- ♥ Macos编译x86_64相关二09/05
- ♥ Windows 核心编程 _ 用户模式:线程同步一07/15
- ♥ Linux 信号处理二03/27
- ♥ COM组件_101/31