浏览器原理学习笔记07—浏览器安全
Write By CS逍遥剑仙 我的主页: www.csxiaoyao.com GitHub: github.com/csxiaoyaojianxian Email: sunjianfeng@csxiaoyao.com
1. Web 页面安全
1.1 同源策略 (Same-origin policy)
协议、域名 和 端口 都相同的两个 URL 同源,默认可以相互访问资源和操作 DOM,两个不同源之间通过安全策略制约隔离 DOM、页面数据和网络通信来保障隐私和数据安全。
- DOM
同源策略限制了不同源的 JavaScript 脚本对当前 DOM 对象的读写操作。例如打开两个同源页面,控制台中执行下面代码,第一个页面 body 被隐藏。
代码语言:txt复制let pdom = opener.document // opener 对象指向第一个页面的 window 对象
pdom.body.style.display = "none"
若不同源页面执行上面代码,会报错:
代码语言:txt复制Blocked a frame with origin "https://www.csxiaoyao.com" from accessing a cross-origin frame.
- Web 数据
同源策略限制了不同源站点间读取 Cookie、IndexDB、LocalStorage 等数据。
- 网络
同源策略限制了通过 XMLHttpRequest 等方式发送数据给不同源的站点。
1.2 安全与效率的平衡
为兼顾效率,目前的页面安全策略所做的平衡:
- 内容安全策略(CSP)
最初的浏览器页面都支持引用外部 js、css 等第三方资源文件(如 CDN 服务资源部署在其他域名),但存在 XSS 安全问题,因此引入 CSP 来让服务器决定浏览器中资源的加载和内联 JavaScript 代码的执行。
- 跨域资源共享(CORS)策略
同源策略限制了不同源页面间使用 XMLHttpRequest 或 Fetch 无法直接进行跨域请求,大大制约生产力,因此引入 CORS 策略安全地进行跨域操作。
- 跨文档消息机制(postMessage)
不同源的 DOM 是不能相互操纵的,降低了效率,因此引入跨文档消息机制,通过 window.postMessage
的 JavaScript 接口进行不同源的 DOM 通信。
1.3 XSS 攻击
1.3.1 概念
XSS 全称 跨站脚本 (Cross Site Scripting),为与 CSS 区分,简称 XSS,由浏览器 支持页面中第三方资源引用 和 CORS 特性引起,表现为黑客在 HTML 文件或 DOM 中注入恶意脚本实行攻击。现在注入恶意脚本的方式已不局限于跨域实现,但仍沿用了 跨站脚本 的名称。恶意脚本能够:
- 窃取 Cookie 信息
通过 document.cookie
获取 Cookie 信息,然后通过 XMLHttpRequest 或 Fetch 配合 CORS 上传数据到恶意服务器,恶意服务器再在其他电脑上根据获取的用户 Cookie 模拟登录态并操作
- 监听用户行为
使用 addEventListener 接口监听键盘事件,获取用户输入并发送到恶意服务器
- 修改 DOM
伪造登录窗口获取用户账号密码
- 在页面内生成浮窗广告
严重影响用户体验
1.3.2 恶意脚本注入方式
1.3.2.1 存储型 XSS 攻击
- 黑客利用站点漏洞将一段恶意 JavaScript 代码提交到网站数据库中
- 用户向网站请求包含了恶意 JavaScript 脚本的页面
- 当用户浏览该页面时恶意脚本将用户 Cookie 等数据通过 XMLHttpRequest 或 Fetch 上传到服务器(用于模拟用户登录)
1.3.2.2 反射型 XSS 攻击
反射型 XSS 攻击过程中,恶意 JavaScript 脚本属于用户发送给网站请求中的一部分,随后网站又把恶意 JavaScript 脚本返回给用户。当恶意 JavaScript 脚本在用户页面中被执行时,黑客就可以利用该脚本做一些恶意操作。
Web 服务器不会存储反射型 XSS 攻击的恶意脚本,黑客经常会通过 QQ 群或邮件等渠道诱导用户去点击形如 http://xxx.com/xxx?xss=<script>alert('你被xss攻击了')</script>
的恶意链接。
1.3.2.3 基于 DOM 的 XSS 攻击
在 Web 资源传输过程或在用户使用页面过程中修改 Web 页面数据,不牵涉到 Web 服务器。例如通过网络劫持(WiFi 路由器劫持、本地恶意软件劫持等)在页面传输过程中修改 HTML 内容。
1.3.3 XSS 防范
存储型和反射型 XSS 攻击属于服务端安全漏洞,基于 DOM 的 XSS 攻击属于前端安全漏洞,共同点是先往浏览器中注入恶意脚本,再通过恶意脚本将用户信息发送至恶意服务器上,所以可以通过阻止恶意 JavaScript 脚本的注入和恶意消息的发送来实现 XSS 防范。
- 服务器对输入脚本进行过滤或转码
- 充分利用 CSP
- 限制加载其他域的资源文件,使黑客插入的 JavaScript 文件无法被加载
- 禁止向第三方域提交数据,Cookie 不会被上传恶意服务器
- 禁止执行内联脚本和未授权脚本
- 提供上报机制尽快发现 XSS 攻击,以便尽快修复
- 使用 Cookie 的 HttpOnly 属性
XSS 攻击最终需要上传 Cookie,服务器可以通过 HTTP 响应头来为某些重要数据 Cookie 添加 HttpOnly 标志。使用 HttpOnly 标记的 Cookie 只能使用在 HTTP 请求过程中,恶意代码无法通过 JavaScript 的 document.cookie 方法读取。
- 其他
通过验证码防止冒充用户提交的危险操作脚本执行;限制输入长度以增大 XSS 攻击的难度。
1.4 CSRF 攻击
1.4.1 概念
CSRF 全称 跨站请求伪造 (Cross-site request forgery),黑客利用用户的登录态,并通过第三方站点发起跨站请求。和 XSS 不同,CSRF 攻击不需要注入恶意代码,仅利用服务器漏洞和用户登录状态实施攻击。
1.4.2 攻击方式
假设已有一个转账接口:https://csxiaoyao.com/sendcoin
,同时支持 GET / POST,参数为:目标用户 user 和金额 number。当用户打开黑客页后,黑客有三种方式实施 CSRF 攻击:
- 自动发起 GET 请求
<html>
<body>
<h1> 黑客的站点:CSRF 攻击演示 </h1>
<img src="https://csxiaoyao.com/sendcoin?user=hacker&number=100">
</body>
</html>
当该页面被加载时,浏览器会自动发起 img 的资源请求。
- 自动发起 POST 请求
<html>
<body>
<h1> 黑客的站点:CSRF 攻击演示 </h1>
<form id='hacker-form' action="https://csxiaoyao.com/sendcoin" method=POST>
<input type="hidden" name="user" value="hacker" />
<input type="hidden" name="number" value="100" />
</form>
<script> document.getElementById('hacker-form').submit(); </script>
</body>
</html>
当用户打开该站点后,表单会被自动执行提交。
- 引诱用户点击链接
<div>
<a href="https://csxiaoyao.com/sendcoin?user=hacker&number=100" taget="_blank">
点击下载美女照片
</a>
</div>
引诱用户点击链接方式通常出现在论坛或恶意邮件上。
1.4.3 CSRF 防范
CSRF 攻击的必要条件:
- 目标站点存在 CSRF 漏洞(关键)
- 浏览器中保持目标站点的登录状态(用户登录过)
- 需要用户打开一个第三方站点(黑客站点、论坛等)
与 XSS 攻击不同,CSRF 攻击不会往页面注入恶意脚本,因此黑客无法获取用户数据。防范的关键在于提升服务器的安全性,如:
- 使用 Cookie 的 SameSite 属性
在 HTTP 响应头中对 Cookie 设置 SameSite 属性来禁止第三方站点发起的请求携带某些关键 Cookie,SameSite 三个选项:
- Strict:完全禁止第三方 Cookie
- Lax:允许第三方站点的链接打开和 GET 提交表单携带 Cookie,而 POST 或通过 img、iframe 等标签加载的 URL 不携带 Cookie
- None:无限制随意发送
例如原站点响应头中的多个 Cookie 格式如下,第三方站点发起请求时只会携带其中 b_value 的 Cookie 值。
代码语言:txt复制set-cookie: a_value=avalue_xxx; expires=Thu, 23-Apr-2020 00:00:31 GMT; path=/; domain=.csxiaoyao.com; SameSite=strict
set-cookie: b_value=bvalue_xxx; expires=Thu, 23-Apr-2020 00:00:31 GMT; path=/; domain=.csxiaoyao.com; SameSite=none
- 验证请求的来源站点
可以在服务器端根据 HTTP 请求头中的 Referer(仅含域名信息) 和 Origin(含具体URL路径) 属性验证请求的来源地址。
有些站点因为安全考虑,不想把源站点的详细路径暴露给服务器,因此浏览器提供给开发者一个选项,可以不上传 Referer 值,具体可参考 Referrer Policy。在一些重要场合,如通过 XMLHttpRequest、Fecth 发起跨站请求或发送 POST 请求时,都会带上 Origin 属性。
服务器的策略是优先判断请求头中的 Origin,若没有再根据实际情况判断是否使用 Referer 值。
- CSRF Token
在浏览器向服务器发起请求时,服务器生成一串 CSRF Token 并植入到当前页面中,如:
代码语言:txt复制<html>
<body>
<form action="https://csxiaoyao.com/sendcoin" method="POST">
<input type="hidden" name="csrf-token" value="iydc9ajDpncYhoadjolcnnc98P987bc">
<input type="text" name="user">
<input type="text" name="number">
<input type="submit">
</form>
</body>
</html>
还可以在用户登录时存储在 head 的 meta 标签中,方便在统一的请求拦截器中获取。当浏览器端发起转账请求时需要带上页面中的 CSRF Token,服务器会验证 Token 的合法性。第三方站点发出的请求将无法获取到正确的 CSRF Token 值而被拒绝。
1.5 页面安全总结
Web 页面安全问题产生的主要原因是浏览器为同源策略开的两个"后门":支持页面中第三方资源引用 和 允许通过 CORS 策略使用 XMLHttpRequest 或 Fetch 跨域请求资源。为解决这些问题,引入 CSP 限制页面任意引入外部资源;引入 HttpOnly 禁止 XMLHttpRequest 或 Fetch 发送关键 Cookie;引入 SameSite 和 Origin 防止 CSRF 攻击。
2. 浏览器系统安全
2.1 单进程浏览器的系统安全缺陷
单进程架构的浏览器除了不稳定,还存在严重的安全问题。若浏览器被爆出漏洞且未及时修复,黑客就可能通过恶意页面向浏览器注入恶意程序,最常见的是利用缓冲区溢出入侵到浏览器进程内部,甚至穿透浏览器威胁操作系统安全,远比 XSS 漏洞可怕。
2.2 现代浏览器架构设计——安全沙箱
现代浏览器被划分为 浏览器内核 和 渲染内核 两个核心模块,其中浏览器内核由 网络进程、浏览器主进程 和 GPU 进程 组成,渲染内核就是 渲染进程。浏览器内核和渲染进程间通过 IPC 通信,如网络资源先通过浏览器内核下载,再通过 IPC 提交给渲染进程;渲染进程经过解析资源、绘制等操作,将最终生成的图片通过 IPC 提交给浏览器内核模块来渲染显示。
渲染进程需要执行 DOM 解析、CSS 解析、网络图片解码等操作,若存在漏洞,黑客很容易利用渲染进程执行下载的恶意网络内容发起攻击。现代浏览器的 安全沙箱 利用操作系统提供的安全技术将渲染进程和操作系统隔离,渲染进程在执行过程中无法访问或修改操作系统中的数据,因此用户将无法获取渲染进程之外的任何操作权限。渲染进程对系统资源的访问则通过浏览器内核的 IPC 通信来实现。
Tips: 安全沙箱最小的保护单位是进程,所以只有多进程的现代浏览器架构才能使用。
2.3 安全沙箱与操作系统的交互
由于渲染进程采用安全沙箱,所以在渲染进程内部不能与操作系统直接交互,于是在浏览器内核中实现了持久存储、网络访问和用户交互等与操作系统交互的功能,通过 IPC 与渲染进程交互。
2.3.1 持久存储
安全沙箱阻止了渲染进程的 Cookie、文件缓存 等直接访问文件系统。例如 Cookie,浏览器内核会维护一个 Cookie 数据库,当渲染进程通过 JavaScript 读取 Cookie 时会通过 IPC 通知浏览器内核,浏览器内核读取 Cookie 后再将内容通过 IPC 返回给渲染进程。
2.3.2 网络访问
安全沙箱阻止了渲染进程直接访问网络,需要通过浏览器内核获取网络资源。浏览器内核会对 URL 做额外权限检查,如同源策略、HTTPS 站点是否包含 HTTP 请求等。
2.3.3 用户交互
通常 UI 程序需要在操作系统提供的窗口句柄上进行绘制和接收键鼠消息。安全沙箱阻止了渲染进程直接访问窗口句柄和监听用户输入,转移到浏览器内核中实现。渲染进程渲染出位图发送到浏览器内核,由浏览器内核将位图复制到屏幕上;所有的键鼠事件由浏览器内核接收,再根据界面状态进行事件调度,如焦点位于地址栏中由浏览器内核处理,位于页面区域内则通过 IPC 将输入事件转发给渲染进程。
2.4 站点隔离(Site Isolation)策略
最开始 Chrome 划分渲染进程是以标签页为单位,所以一个标签页中多个不同源的 iframe 也会被分配到同一个渲染进程中,很容易让黑客通过 iframe 攻击当前渲染进程。Chrome 几年前开始重构代码,严格按照 同一站点(根域名 协议相同,区别于同源)的策略分配渲染进程。使用站点隔离后,不同站点的 iframe 分配到相互隔离的渲染进程中,即使渲染进程被攻击,也无法继续访问其他站点渲染进程的内容。2019 年 10 月 20 日 Chrome 团队宣布安卓版 Chrome 已全面支持站点隔离。
Tips: 目前所有操作系统都面临两个由处理器架构缺陷导致的很难修补 A 级漏洞——幽灵(Spectre)和熔毁(Meltdown),黑客很容易通过 A 级漏洞攻击渲染进程,因此站点隔离策略很重要。
渲染进程数量和标签页的联系:
- 若两个标签页位于 同一浏览上下文组 (页面通过 window.opener 相互联系,如页面1通过 a 标签或 js 代码打开了页面2),且属于 同一站点 (不一定同源),则两个标签页会被分配到同一个渲染进程中,否则分配独立的渲染进程。
- 例外:若 a 标签中加入
rel=noopener
属性,通过链接打开的新标签页会新分配渲染进程,和源标签页不建立连接关系。 - 站点隔离对渲染进程的分配策略如上。
3. 浏览器网络安全
3.1 HTTPS & 安全层
HTTP 的明文传输数据提交给 TCP 层后,数据会经过用户电脑、WiFi 路由器、运营商和目标服务器,中间的每个环节数据都可能被窃取或篡改,即 中间人攻击,因此引入 HTTPS 来解决。
HTTPS 并非新协议,而是在 HTTP 协议栈的 TCP 和 HTTP 层之间插入一个 安全层 负责数据加密解密操作。
接下来利用这个安全层,一步步实现一个从简单到复杂的 HTTPS 协议。
第一版:使用对称加密
对称加密即加密和解密都使用相同的密钥。览器端和服务器协商确定加密套件(加密方法)和随机数,再使用相同的加密方法将 client-random 和 service-random 混合起来生成一个密钥 master secret,然后进行数据加密传输。但由于密匙明文传输,黑客很容易伪造或篡改数据。
第二版:使用非对称加密
非对称加密指算法有 A、B 两把密钥,其中一把用来加密,另一把就用来解密。服务器将其中的一个密钥作为公钥明文发送给浏览器并对外公开,而另一个作为私钥不对外公开。但非对称加密不仅效率低,且公钥公开,不能保证服务器端发送给浏览器端的数据安全。
第三版:对称加密和非对称加密搭配使用
结合前两版,传输数据阶段依然使用高效的对称加密,而对称加密的密钥采用非对称加密来传输,解决了效率和两端数据安全传输的问题。由于 pre-master 是经公钥加密后传输的,因此黑客无法获取并生成密钥,也就无法破解传输过程中的数据。
第四版:添加数字证书
第三版已经完美地实现了数据的加密安全传输,但无法解决 DNS 劫持问题,黑客仍然可以替换目标 IP,在恶意服务器上生成公钥私钥,即无法证明"我就是我"。因此浏览器引入了 数字证书 (Digital Certificate),由权威机构 CA (Certificate Authority) 颁发。
数字证书里包含了服务器公钥,浏览器端也增加了证书验证的操作。由于证书是由 CA 签名过的,无法伪造,所以浏览器实现了对服务器的身份认证。
3.2 数字证书
3.2.1 数字证书的申请
首先准备一套私钥和公钥并向 CA 机构提交相关信息(不含私钥),审核通过后 CA 会签发数字证书,包含各种明文信息(准备的公钥、组织信息、CA 信息、有效时间、证书序列号等) 和一个 CA 生成的签名。
CA 生成签名: 首先 CA 使用 Hash 函数计算证书的明文信息并得出信息摘要;然后再使用 CA 的私钥 对信息摘要进行加密,密文即为 CA 签发的数字签名。可通过数字签名来验证证书是否是该 CA 颁发的。
3.2.2 数字证书的验证
浏览器向服务器发出请求时,服务器会返回 CA 签名过的数字证书给浏览器。浏览器需要验证 证书有效期、证书是否被 CA 吊销、证书是否由合法的 CA 机构颁发。
验证数字证书是否被吊销: 通常有两种方式:下载吊销证书列表 CRL (Certificate Revocation Lists) 和在线验证 OCSP (Online Certificate Status Protocol)。
验证证书是否由合法的 CA 机构颁发:浏览器使用签名时相同的 Hash 函数计算证书明文信息并得到信息摘要对比用 CA 公钥解密签名数据得到信息摘要,若一致则可以确认证书合法。
注意: 这里的 CA 公钥不是当前证书的公钥,而是颁发证书的 CA 的公钥,CA 证书一般随同当前网站证书部署在服务器中;若未部署则浏览器通过网络下载,一般不推荐。
前面只验证了 CA 的来源可靠性,但浏览器不能确定 CA 机构的合法性。目前通过 WebTrust 认证的根 CA 有 Comodo、geotrust、rapidssl、symantec、thawte、digicert 等,这些根 CA 机构的根证书都内置在各大操作系统中,只要能从 数字证书链 往上追溯到这几个根证书,浏览器就会认为使用者的证书是合法的。
数字证书链: 根证书(自签名证书)是最权威的机构在浏览器中内置的为自己签名的数字证书,一个根CA(Root CAs)会认证很多中间CA(Intermediates CAs),形成数字证书链。
浏览器默认信任操作系统内置的根证书,但黑客也可能向系统中添加恶意根数字证书,所以 HTTPS 只是加固了安全防线,并非绝对安全。