安全沙盒机制

1/31/2023 浏览器进程浏览器漏洞缓冲区溢出站点隔离沙盒机制进程操作系统

# 前言

初期单进程架构浏览器,从稳定性角度看是不稳定的,浏览器进程中任意功能出现异常都有可能影响整个浏览器(页面卡死、浏览器崩溃),同时从安全性的角度看,浏览器的架构也关乎操作系统的安全,当浏览器本身存在漏洞且未修复,黑客可以通过恶意页面对浏览器进行攻击(缓冲区溢出),相较于XSS攻击是将JS脚本注入页面窃取Cookie等信息,但XSS无法对操作系统进行攻击,但是对浏览器进行的攻击可以入侵浏览器进程内部,可以读取修改浏览器进程的所有内容,甚至穿透浏览器,在操作系统上安装恶意软件,监听用户键盘输入信息,读取用户硬盘内容。所以此类攻击相较于XSS攻击更加严重,让操作系统的安全得不到保障。

# 多进程架构

为了解决这种威胁,现代浏览器架构划分为两个核心模块:

  1. 浏览器内核 => 浏览器主进程 + 网络进程 + GPU进程
  2. 渲染内核 => 渲染进程 工作流:
  3. 浏览器内核负责所有网络资源的下载,下载后的资源通过IPC提交给渲染进程(浏览器内核、渲染进程通过IPC通信)。
  4. 渲染进程对资源进行解析、绘制,生成图片,将生成的图片提交给浏览器内核,浏览器内核负责显示这张图片。

# 安全沙箱

渲染进程需要执行DOM解析、CSS解析、网络图片解码,如果渲染进程出现漏洞,那么上述操作可能让恶意网点获取渲染进程控制权限,进而获得操作系统控制权限。浏览器对于网络资源默认为不可信的,但浏览器自身漏洞是没办法避免的,所以浏览器执行下载的网络资源需要谨慎,解析HTML、CSS、执行JS,一旦浏览器自身出现漏洞就会被这些操作发起攻击。所以我们需要在渲染进程和操作系统之间加上一道墙,即使渲染进程存在漏洞被攻击,但由于安全墙的存在,黑客无法获取渲染进程之外的任何权限,这道墙就是安全沙箱。

浏览器的安全沙箱利用操作系统提供的安全技术,让渲染进程在执行过程中无法访问或者修改操作系统中的数据,在渲染进程需要访问系统资源的时候,需要通过浏览器内核来实现,然后将访问的结果通过IPC转发给渲染进程。

安全沙箱最小的保护单位是进程,单进程浏览器需要频繁访问或修改操作系统的数据,所以单进程浏览器是无法被安全沙箱保护的,现代浏览器采用的多进程架构使得安全沙箱可以发挥作用。

# 相关模块

要让安全沙箱应用在某个进程上,那么这个进程必须没有读写操作系统的功能,比如读写本地文件、发起网络请求、调用GPU接口等等,被安全沙箱保护的进程会有一系列的受限操作。

# 持久存储

安全沙箱需要负责确保渲染进程无法直接访问用户的文件系统,但是在渲染进程内部有访问Cookie的需求、上传文件的需求,为了解决这些文件的访问需求,所以现代浏览器将读写文件的操作全部放在了浏览器内核中实现,然后通过IPC将操作结果转发给渲染进程。
在浏览器内核中完成的文件内容的读写:存储Cookie数据的读写,通常浏览器内核会维护一个存放所有Cookie的数据库,然后当渲染进程通过JavaScript来读取Cookie时,渲染进程会通过IPC将读取Cookie的信息发送给浏览器内核,浏览器内核读取Cookie之后再将内容返回给渲染进程。一些缓存文件的读写也是由浏览器内核实现的,比如网络文件缓存的读取。

# 网络访问

有了安全沙箱的保护,在渲染进程内部是不能直接访问网络的,如果要访问网络,则需要通过浏览器内核,浏览器内核在处理URL请求之前,会检查渲染进程是否有权限请求该URL,比如检查XMLHttpRequest或Fetch是否是跨站点请求,或检测HTTPS的站点中是否包含了HTTP的请求。

# 用户交互

渲染进程的安全沙箱还影响到了一个非常重要的用户交互功能。如果要实现一个UI程序,操作系统会提供一个界面给你,该界面允许应用程序与用户交互,允许应用程序在该界面上进行绘制,比如Windows提供的是HWND,Linux提供的X Window,我们就把HWND和X Window统称为窗口句柄。应用程序可以在窗口句柄上进行绘制和接收键盘鼠标消息。在现代浏览器中,由于每个渲染进程都有安全沙箱的保护,所以在渲染进程内部是无法直接操作窗口句柄的,这也是为了限制渲染进程监控到用户的输入事件。
由于渲染进程不能直接访问窗口句柄,所以渲染进程需要完成以下两点大的改变:

  1. 渲染进程需要渲染出位图。为了向用户显示渲染进程渲染出来的位图,渲染进程需要将生成好的位图发送到浏览器内核,然后浏览器内核将位图复制到屏幕上。
  2. 操作系统没有将用户输入事件直接传递给渲染进程,而是将这些事件传递给浏览器内核。然后浏览器内核再根据当前浏览器界面的状态来判断如何调度这些事件,如果当前焦点位于浏览器地址栏中,则输入事件会在浏览器内核内部处理;如果当前焦点在页面的区域内,则浏览器内核会将输入事件转发给渲染进程。之所以这样设计,就是为了限制渲染进程有监控到用户输入事件的能力,所以所有的键盘鼠标事件都是由浏览器内核来接收的,然后浏览器内核再通过IPC将这些事件发送给渲染进程。

# 站点隔离(Site Isolation)

站点隔离是指Chrome将同一站点(包含了相同根域名和相同协议的地址)中相互关联的页面放到同一个渲染进程中执行。最开始Chrome划分渲染进程是以标签页为单位,也就是说整个标签页会被划分给某个渲染进程。但是,按照标签页划分渲染进程存在一些问题,原因就是一个标签页中可能包含了多个iframe,而这些iframe又有可能来自于不同的站点,这就导致了多个不同站点中的内容通过iframe同时运行在同一个渲染进程中。目前所有操作系统都面临着两个A级漏洞——幽灵(Spectre)和熔毁(Meltdown),这两个漏洞是由处理器架构导致的,很难修补,黑客通过这两个漏洞可以直接入侵到进程的内部,如果入侵的进程没有安全沙箱的保护,那么黑客还可以发起对操作系统的攻击。所以如果一个银行站点包含了一个恶意iframe,然后这个恶意的iframe利用这两个A级漏洞去入侵渲染进程,那么恶意程序就能读取银行站点渲染进程内的所有内容了,这对于用户来说就存在很大的风险了。
因此Chrome就开始重构代码,将标签级的渲染进程重构为iframe级的渲染进程,然后严格按照同一站点的策略来分配渲染进程,这就是 Chrome中的站点隔离。实现了站点隔离,就可以将恶意的iframe隔离在恶意进程内部,使得它无法继续访问其他iframe进程的内容,因此也就无法攻击其他站点了。2019年10月20日Chrome团队宣布安卓版的Chrome全面支持站点隔离。

# 总结

渲染进程引入了安全沙箱,所以浏览器的持久存储、网络访问、用户交互等功能都不能在渲染进程内直接使用了,所以需要把这些功能迁移到浏览器内核中去实现,让原本比较简单的流程变得复杂了。

Last Updated: 2/8/2023, 2:15:46 PM