极客时间已完结课程限时免费阅读

35 | 安全沙箱:页面和系统之间的隔离墙

35 | 安全沙箱:页面和系统之间的隔离墙-极客时间

35 | 安全沙箱:页面和系统之间的隔离墙

讲述:李兵

时长14:51大小11.88M

前面三篇文章我们主要围绕同源策略介绍了 Web 页面安全的相关内容,那今天我们把视野向外延伸,来聊聊页面安全和操作系统安全之间的关系。
《01 | Chrome 架构:仅仅打开了 1 个页面,为什么有 4 个进程?》那篇文章中,我们分析了浏览器架构的发展史,在最开始的阶段,浏览器是单进程的,这意味着渲染过程、JavaScript 执行过程、网络加载过程、UI 绘制过程和页面显示过程等都是在同一个进程中执行的,这种结构虽然简单,但是也带来了很多问题。
从稳定性视角来看,单进程架构的浏览器是不稳定的,因为只要浏览器进程中的任意一个功能出现异常都有可能影响到整个浏览器,如页面卡死、浏览器崩溃等。不过浏览器的稳定性并不是本文讨论的重点,我们今天主要聊的是浏览器架构是如何影响到操作系统安全的
浏览器本身的漏洞是单进程浏览器的一个主要问题,如果浏览器被曝出存在漏洞,那么在这些漏洞没有被及时修复的情况下,黑客就有可能通过恶意的页面向浏览器中注入恶意程序,其中最常见的攻击方式是利用缓冲区溢出,不过需要注意这种类型的攻击和 XSS 注入的脚本是不一样的
XSS 攻击只是将恶意的 JavaScript 脚本注入到页面中,虽然能窃取一些 Cookie 相关的数据,但是 XSS 无法对操作系统进行攻击。
而通过浏览器漏洞进行的攻击是可以入侵到浏览器进程内部的,可以读取和修改浏览器进程内部的任意内容,还可以穿透浏览器,在用户的操作系统上悄悄地安装恶意软件、监听用户键盘输入信息以及读取用户硬盘上的文件内容。
和 XSS 攻击页面相比,这类攻击无疑是枚“核弹”,它会将整个操作系统的内容都暴露给黑客,这样我们操作系统上所有的资料都是不安全的了。

安全视角下的多进程架构

现代浏览器的设计目标是安全、快速稳定,而这种核弹级杀伤力的安全问题就是一个很大的潜在威胁,因此在设计现代浏览器的体系架构时,需要解决这个问题。
我们知道现代浏览器采用了多进程架构,将渲染进程和浏览器主进程做了分离,完整的进程架构我们已经在《01 | Chrome 架构:仅仅打开了 1 个页面,为什么有 4 个进程?》那篇文章中介绍过了,这里我就不重复介绍了。下面我们重点从操作系统安全的视角来看看浏览器的多进程架构,如下图:
浏览器内核和渲染进程
观察上图,我们知道浏览器被划分为浏览器内核渲染内核两个核心模块,其中浏览器内核是由网络进程、浏览器主进程和 GPU 进程组成的,渲染内核就是渲染进程。那如果我们在浏览器中打开一个页面,这两个模块是怎么配合的呢?
所有的网络资源都是通过浏览器内核来下载的,下载后的资源会通过 IPC 将其提交给渲染进程(浏览器内核和渲染进程之间都是通过 IPC 来通信的)。然后渲染进程会对这些资源进行解析、绘制等操作,最终生成一幅图片。但是渲染进程并不负责将图片显示到界面上,而是将最终生成的图片提交给浏览器内核模块,由浏览器内核模块负责显示这张图片。
《01 | Chrome 架构:仅仅打开了 1 个页面,为什么有 4 个进程?》中我们分析过,设计现代浏览器体系架构时,将浏览器划分为不同的进程是为了增加其稳定性。虽然设计成了多进程架构,不过这些模块之间的沟通方式却有些复杂,也许你还有以下问题:
为什么一定要通过浏览器内核去请求资源,再将数据转发给渲染进程,而不直接从进程内部去请求网络资源?
为什么渲染进程只负责生成页面图片,生成图片还要经过 IPC 通知浏览器内核模块,然后让浏览器内核去负责展示图片?
通过以上方式不是增加了工程的复杂度吗?
要解释现代浏览器为什么要把这个流程弄得这么复杂,我们就得从系统安全的角度来分析。

安全沙箱

不过在解释这些问题之前,我们得先看看什么是安全沙箱。
上面我们分析过了,由于渲染进程需要执行 DOM 解析、CSS 解析、网络图片解码等操作,如果渲染进程中存在系统级别的漏洞,那么以上操作就有可能让恶意的站点获取到渲染进程的控制权限,进而又获取操作系统的控制权限,这对于用户来说是非常危险的。
因为网络资源的内容存在着各种可能性,所以浏览器会默认所有的网络资源都是不可信的,都是不安全的。但谁也不能保证浏览器不存在漏洞,只要出现漏洞,黑客就可以通过网络内容对用户发起攻击。
我们知道,如果你下载了一个恶意程序,但是没有执行它,那么恶意程序是不会生效的。同理,浏览器之于网络内容也是如此,浏览器可以安全地下载各种网络资源,但是如果要执行这些网络资源,比如解析 HTML、解析 CSS、执行 JavaScript、图片编解码等操作,就需要非常谨慎了,因为一不小心,黑客就会利用这些操作对含有漏洞的浏览器发起攻击。
基于以上原因,我们需要在渲染进程和操作系统之间建一道墙,即便渲染进程由于存在漏洞被黑客攻击,但由于这道墙,黑客就获取不到渲染进程之外的任何操作权限。将渲染进程和操作系统隔离的这道墙就是我们要聊的安全沙箱
浏览器中的安全沙箱是利用操作系统提供的安全技术,让渲染进程在执行过程中无法访问或者修改操作系统中的数据,在渲染进程需要访问系统资源的时候,需要通过浏览器内核来实现,然后将访问的结果通过 IPC 转发给渲染进程。
安全沙箱最小的保护单位是进程。因为单进程浏览器需要频繁访问或者修改操作系统的数据,所以单进程浏览器是无法被安全沙箱保护的,而现代浏览器采用的多进程架构使得安全沙箱可以发挥作用。

安全沙箱如何影响各个模块功能

我们知道安全沙箱最小的保护单位是进程,并且能限制进程对操作系统资源的访问和修改,这就意味着如果要让安全沙箱应用在某个进程上,那么这个进程必须没有读写操作系统的功能,比如读写本地文件、发起网络请求、调用 GPU 接口等。
了解了被安全沙箱保护的进程会有一系列的受限操作之后,接下来我们就可以分析渲染进程和浏览器内核各自都有哪些职责,如下图:
浏览器内核和渲染进程各自职责
通过该图,我们可以看到由于渲染进程需要安全沙箱的保护,因此需要把在渲染进程内部涉及到和系统交互的功能都转移到浏览器内核中去实现。
那安全沙箱是如何影响到各个模块功能的呢?

1. 持久存储

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

2. 网络访问

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

3. 用户交互

渲染进程实现了安全沙箱,还影响到了一个非常重要的用户交互功能。
通常情况下,如果你要实现一个 UI 程序,操作系统会提供一个界面给你,该界面允许应用程序与用户交互,允许应用程序在该界面上进行绘制,比如 Windows 提供的是 HWND,Linux 提供的 X Window,我们就把 HWND 和 X Window 统称为窗口句柄。应用程序可以在窗口句柄上进行绘制和接收键盘鼠标消息。
不过在现代浏览器中,由于每个渲染进程都有安全沙箱的保护,所以在渲染进程内部是无法直接操作窗口句柄的,这也是为了限制渲染进程监控到用户的输入事件。
由于渲染进程不能直接访问窗口句柄,所以渲染进程需要完成以下两点大的改变。
第一点,渲染进程需要渲染出位图。为了向用户显示渲染进程渲染出来的位图,渲染进程需要将生成好的位图发送到浏览器内核,然后浏览器内核将位图复制到屏幕上。
第二点,操作系统没有将用户输入事件直接传递给渲染进程,而是将这些事件传递给浏览器内核。然后浏览器内核再根据当前浏览器界面的状态来判断如何调度这些事件,如果当前焦点位于浏览器地址栏中,则输入事件会在浏览器内核内部处理;如果当前焦点在页面的区域内,则浏览器内核会将输入事件转发给渲染进程。
之所以这样设计,就是为了限制渲染进程有监控到用户输入事件的能力,所以所有的键盘鼠标事件都是由浏览器内核来接收的,然后浏览器内核再通过 IPC 将这些事件发送给渲染进程。
上面我们分析了由于渲染进程引入了安全沙箱,所以浏览器的持久存储、网络访问和用户交互等功能都不能在渲染进程内直接使用了,因此我们需要把这些功能迁移到浏览器内核中去实现,这让原本比较简单的流程变得复杂了。
理解这些限制,我们就能解释开始提出的两个问题了。

站点隔离(Site Isolation)

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

总结

好了,今天的内容就介绍到这里,下面我来总结下本文的主要内容。
首先我们分析了单进程浏览器在系统安全方面的不足,如果浏览器存在漏洞,那么黑客就有机会通过页面对系统发起攻击。
因此在设计现代浏览器的体系架构时,就考虑到这个问题了。于是,在多进程的基础之上引入了安全沙箱,有了安全沙箱,就可以将操作系统和渲染进程进行隔离,这样即便渲染进程由于漏洞被攻击,也不会影响到操作系统的。
由于渲染进程采用了安全沙箱,所以在渲染进程内部不能与操作系统直接交互,于是就在浏览器内核中实现了持久存储、网络访问和用户交互等一系列与操作系统交互的功能,然后通过 IPC 和渲染进程进行交互。
最后我们还分析了 Chrome 中最新的站点隔离功能。由于最初都是按照标签页来划分渲染进程的,所以如果一个标签页里面有多个不同源的 iframe,那么这些 iframe 也会被分配到同一个渲染进程中,这样就很容易让黑客通过 iframe 来攻击当前渲染进程。而站点隔离会将不同源的 iframe 分配到不同的渲染进程中,这样即使黑客攻击恶意 iframe 的渲染进程,也不会影响到其他渲染进程的。
今天介绍的内容和概念都比较多,看上去离前端比较远,不过这些内容会影响你对浏览器整体架构的理解,而深入理解了浏览器架构能帮助你更加深刻地理解前端内容。为了方便你的理解,我把一些参考资料放到了文章的最后,有需要的话你可以拿来参考。

思考时间

今天留给你的思考题:你认为安全沙箱能防止 XSS 或者 CSRF 一类的攻击的吗?为什么?
欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友。

参考资料

分享给需要的人,Ta购买本课程,你将得18
生成海报并分享

赞 20

提建议

上一篇
34 | CSRF攻击:陌生链接不要随便点
下一篇
36 | HTTPS:让数据传输更安全
unpreview
 写留言

精选留言(32)

  • 一步
    2019-10-24
    安全沙箱是不能防止 XSS 或者 CSRF 一类的攻击, 安全沙箱的目的是隔离渲染进程和操作系统,让渲染进行没有访问操作系统的权利 XSS 或者 CSRF 主要是利用网络资源获取用户的信息,这和操作系统没有关系的

    作者回复: 没问题

    68
  • 成楠Peter
    2019-10-24
    每周都跟着老师一起学习,终于坚持到最后了。千里之行始于足下,课程结束后,我们再向老师提问?

    作者回复: 日拱一卒 不期速成 我随时奉陪

    共 3 条评论
    24
  • 刹那
    2019-10-26
    老师我有个疑问,既然渲染进程运行在沙箱中,涉及到系统操作的都通过ipc向浏览器进程发送操作请求,那么,这个阶段会不会也存在安全漏洞?就是说,渲染进程有没有可能发送一个能攻破浏览器进程的消息,之后可以通过控制浏览器进程入侵操作系统?

    作者回复: 如果ipc有漏洞也是可能的,不过要通过IPC发起攻击、那难度就太大了,因为IPC的消息要合规,不合规的消息也会被过滤掉的。

    22
  • Snow同學
    2019-10-25
    请问老师,这个问题我问了好几遍了,希望得到老师的回复, 在开发时 1.空页面加载一个URL,如何知道页面已经显示在了屏幕上(从用户真实的视觉上看到页面),在代码层面可以通过检测什么状态知道嘛? 2.在页面已经显示到屏幕后完成,通过点击一个按钮,执行向document添加一些元素(可以是div,div里也可以有更多其他标签和内容),如何知道这些元素什么时候真正显示在屏幕上(从用户真实的视觉上看到页面),在代码层面可以通过检测什么状态知道嘛? 是不是无法通过代码检测呀?
    展开

    作者回复: 不好意思,久等了。 你可以关注下 PerformancePaintTiming,不过这个功能个大浏览器还在开发中,Chrome也可以使用,但是不保证准确度。 另外要使用该接口,还需要了解几个概念如First paint、First contentful paint。 这是MDN上的一段代码,你可以测试下: function showPaintTimings() { if (window.performance) { let performance = window.performance; let performanceEntries = performance.getEntriesByType('paint'); performanceEntries.forEach( (performanceEntry, i, entries) => { console.log("The time to " + performanceEntry.name + " was " + performanceEntry.startTime + " milliseconds."); }); } else { console.log('Performance timing isn\'t supported.'); } } 给你两个参考地址 MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/PerformancePaintTiming W3C: https://www.w3.org/TR/paint-timing/

    共 2 条评论
    6
  • 空山鸟语
    2019-10-24
    老师讲的全是干货,目前正在反复听呢! 表示还没听够

    作者回复: 感谢肯定,课程内容的确是非常精心规划的

    6
  • mfist
    2019-10-24
    不能攻击,xss csrf 是攻击的网页服务器的漏洞。跟浏览器本身没有关系。不过应该能使攻击者绕过前端的编码检验之类,如果后端没有对应的安全检验就惨了。

    作者回复: 没问题

    5
  • 李懂
    2019-10-24
    老师多给自己留点坑,多讲讲,还想再学学! 希望能讲讲,全局上下文不是只存在一个么,为啥在执行时js,每次都先创建全局上下文,进栈,是不是哪里理解的有问题?

    作者回复: 坑不少了。 我想想怎么填

    共 2 条评论
    3
  • 李小白
    2019-10-31
    老师,我想请问一下,你说渲染进程内部是无法直接操作窗口句柄的,这也是为了限制渲染进程监控到用户的输入事件,这种情况我也可以通过JS来获取监控到用户的输入事件啊,通过渲染进程,渲染进程是可以通过IPC从浏览器内核监控到用户输入事件的啊,和我们正常用js就是可以获取用户的输入事件一样。希望老师帮忙解答一下

    作者回复: 通过IPC传给渲染进程的是浏览器默许的,这个没有问题。 安全沙箱主要保护的是恶意程序通过网络攻破渲染进程,然后在渲染进程内,获取系统窗口的内容,比如qq登陆窗口这种。

    2
  • man
    2019-10-26
    很精彩呀,像看了一部好莱坞大片的感觉。。。
    共 2 条评论
    2
  • 2019-10-24
    这就完了吗?意犹未尽,每一讲都讲的挺好。每个2,4,6早上到公司都会第一时间check有没有更新,期待后面的问答加餐环节,哈哈

    作者回复: 感谢

    2
  • james
    2020-06-11
    安全沙箱不能防止XSS和CSRF攻击 因为XSS攻击是黑客在页面中注入不合法脚本,导致攻击用户浏览器的问题,是属于渲染进程里面的 CSRF攻击是黑客利用用户的登录状态,是属于利用网络资源获取用户信息,然后黑客通过第三方站点来攻击的目的,这个也是属于渲染进程中的 因此跟安全沙箱没有关系
    展开
    1
  • jyzhang
    2019-12-19
    持久存储 。这里有点疑惑,沙箱里渲染进程将读写cookie和缓存文件的需求用IPC发给浏览器内核处理,内核再把结果用ipc返回,为什么这样就会比较安全?

    作者回复: 因为不让渲染进程有读取系统文件的能力,这样即使黑客通过页面拿到渲染进程的控制权,他也没能力去读写系统的文件!

    共 2 条评论
    1
  • 滇西之王
    2019-10-24
    不能防止,xss攻击和cspf不是针对操作系统的攻击,xss攻击就是执行javascript脚步,他的攻击是在渲染进程内,cspf是发送请求获取用户敏感信息,利用到网络进程

    作者回复: 没问题

    1
  • 亲爱的偏执狂
    2019-10-24
    好快啊,感觉没多久就剩最后一讲就结束了。

    作者回复: 我可不觉得快,都是一天当两天使哈

    1
  • 罗武钢
    2022-09-17 来自广东
    很棒
  • Geek_bing
    2021-08-18
    怎么说,意犹未尽啊!课程干货很多导致自己不知道的感觉也很多了~
  • 张宗伟
    2021-06-17
    Chrome uses a specific definition of "site" that includes just the scheme and registered domain. Thus, https://google.co.uk would be a site, and subdomains like https://maps.google.co.uk would stay in the same process.
  • 张宗伟
    2021-06-17
    老师对于这句话:所谓站点隔离是指 Chrome 将同一站点(包含了相同根域名和相同协议的地址)中相互关联的页面放到同一个渲染进程中执行。 其中 相同根域名 是不是表达的意思不对呀,那如果这样可认为 同一站点 的url可太多了。
  • 张宗伟
    2021-06-11
    安全沙箱的主要作用是 防止通过浏览器直接操作系统的资源,进而造成系统级的安全威胁。 而 XSS、CSRF 主要是发生在渲染进程(页面)与服务器,这些操作都是符合 安全沙箱 的规则的,所以并不能防护。它们所关注的点不一样。
  • William Ning
    2021-03-03
    Js执行实在渲染进程主线程中?