摘要:极客时间《浏览器工作原理与实践》 浏览器安全学习笔记,同源策略、跨站脚本攻击(XSS)、CSRF 攻击、安全沙箱、HTTPS
浏览器安全
浏览器安全可以分为三大块:页面安全、系统安全和网络安全
页面安全
同源策略
如果两个 URL 的协议、域名和端口都相同,则这两个 URL 是同源。浏览器默认两个相同的源之间是可以相互访问资源和操作 DOM 的,而不同的源之间则有一套基础的安全策略——同源策略来制约相互访问资源或操作 DOM。
同源策略主要表现在 3 方面:
1、DOM 层面。同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。
2、数据层面。同源策略限制了不同源的站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据。
3、网络层面。同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。
但安全性和便利性是相互对立的,为了便利性出让了部分安全性:
1、页面中可以引用第三方资源,不过这也暴露了很多诸如 XSS 的安全问题,因此又在这种开放的基础之上引入了 CSP 内容安全策略来限制其自由程度。CSP 的核心思想是让服务器决定浏览器能够加载哪些资源,让服务器决定浏览器是否能够执行内联 JavaScript 代码。
2、使用 XMLHttpRequest 和 Fetch 都是无法直接进行跨域请求的,因此浏览器又在这种严格策略的基础之上引入了 CORS 跨域资源共享策略,让其可以安全地进行跨域操作。
3、两个不同源的 DOM 是不能相互操纵的,因此,浏览器中又实现了跨文档消息机制,通过调用 window.postMessage 的 JavaScript 接口,让其可以比较安全地通信。
XSS
XSS 跨域脚本攻击是指黑客往 HTML 文件中或者 DOM 中注入恶意脚本,从而在用户浏览页面时利用注入的恶意脚本对用户实施攻击的一种手段。当页面被注入了恶意 JavaScript 脚本时,浏览器是无法区分的,所以恶意注入 JavaScript 的脚本也拥有所有的脚本权限。有了所有脚本的权限,那么黑客就可以为所欲为:窃取 Cookie 信息、监听用户行为、修改 DOM、生成浮窗广告等。
注入恶意脚本的方式:
1、存储型 XSS 攻击
攻击步骤:
1)利用网站漏洞将一段恶意 JavaScript 代码提交到网站的数据库中
2)用户向网站请求包含了恶意 JavaScript 脚本的页面
3)恶意脚本执行代码将用户隐私信息上传到服务器
2、反射型 XSS 攻击
用户将一段含有恶意代码的请求提交给 Web 服务器,Web 服务器接收到请求时,又将恶意代码反射给了浏览器端,浏览器又将响应的包含恶意脚本的内容注入到页面中,这就是反射型 XSS 攻击。Web 服务器不会存储反射型 XSS 攻击的恶意脚本,这是和存储型 XSS 攻击不同的地方。
3、基于 DOM 的 XSS 攻击
基于 DOM 的 XSS 攻击是不牵涉到页面 Web 服务器的,它是在 Web 资源传输过程或者在用户使用页面的过程中劫持并修改 Web 页面的数据。比如路由器劫持、本地恶意软件劫持。
阻止 XSS 攻击的方法:
1、服务器对输入脚本进行过滤或转码。过滤掉<script>
标签的内容,或者转码等其他方法破坏<script>
标签的完整性
2、充分利用 CSP。CSP 有如下几个功能:
1)限制加载其他域下的资源文件;
2)禁止向第三方域提交数据,这样用户数据也不会外泄;
3)禁止执行内联脚本和未授权的脚本;
4)提供上报机制,可以尽快发现有哪些 XSS 攻击,以便尽快修复问题
3、使用 HttpOnly 属性
HttpOnly 属性是服务器通过 HTTP 响应头来设置的,使用 HttpOnly 标记的 Cookie 只能使用在 HTTP 请求过程中,所以无法通过 JavaScript 来读取这段 Cookie。通过 Chrome 开发者工具查看 Application 中 Cookies 的 HttpOnly 属性是否打钩来判断是否设置 HttpOnly 标志。
CSRF
CSRF 跨站请求伪造和 XSS 不同的是:CSRF 攻击不需要将恶意代码注入用户的页面,黑客利用用户的登录状态,通过第三方的站点来做一些坏事。用户打开并登录正规的网站,然后被黑客引诱打开黑客的网站页面,此时黑客实施 CSRF 攻击。CSRF 攻击有三种方法:
1、自动发起 GET 请求,比如:页面中有这样的代码<img src="https://hacker.com/transfer?user=hacker&money=100">
,如果服务器不做校验的话,这个请求就是正常的转账请求,钱就会被转走
2、自动发起 POST 请求,比如:页面中有一个表单<form id='hacker-form' action="https://hacker.com/transfer">...</form>
只需要自动发起请求document.getElementById('hacker-form').submit()
,即可将表单内容正常提交到服务器
3、引诱用户点击链接,比如:页面中有<a id='hacker-a' href="https://hacker.com/transfer?user=hacker&money=100">一天赚百万</a>
,一旦点击就会发起请求,当然也可以自动发起请求document.getElementById('hacker-form').click()
发起 CSRF 攻击的三个必要条件:
1、网站有 CSRF 漏洞;
2、用户需要在正规站点保持登录状态;
3、用户打开了黑客或其他第三方的站点
防止 CSRF 攻击的方法:
1、充分利用好 Cookie 的 SameSite 属性
通常维护登录状态的关键数据会存储在 Cookie 中,并且 CSRF 攻击都是从第三方站点发起的,如果从第三方站点发送请求时禁止 Cookie 的发送,那么可以有效降低 CSRF 攻击的风险。
SameSite 选项通常有 Strict、Lax 和 None 三个值。Strict 最为严格,浏览器会完全禁止第三方 Cookie;Lax 相对宽松一点,第三方站点的链接打开和从第三方站点提交 Get 方式的表单这两种方式都会携带 Cookie;设置为 None 则会在任何情况下都会发送 Cookie 数据。根据实际情况将一些关键的 Cookie 设置为 Strict 或者 Lax 模式会使 CSRF 攻击失效。
2、验证请求的来源站点
在服务器端验证请求来源的站点,禁止第三方站点的请求即可。Referer 是 HTTP 请求头中的一个字段,记录了该 HTTP 请求的来源地址,包含了具体的 UTL 路径。Origin 属性则只包含了域名信息,并没有包含具体的 URL 路径。服务器的策略是优先判断 Origin,如果请求头中没有包含 Origin 属性,再根据实际情况判断是否使用 Referer 值。
3、CSRF Token
分为两步:
1)在浏览器发起请求之前,服务器先生成一个 CSRF Token 字符串,并将该字符串植入到返回的页面中;
2)浏览器发生转账请求时,带上 CSRF Token 并服务器验证该 Token 是否合法,而第三方网站是无法获取到 CSRF Token 的
系统安全
浏览器被划分为浏览器内核和渲染内核两个核心模块,其中浏览器内核是由网络进程、浏览器主进程和 GPU 进程组成的,渲染内核就是渲染进程。浏览器内核和渲染进程之间都是通过 IPC 来通信的,当所有的网络资源都由浏览器内核来下载好后,通过 IPC 将资源交给渲染进程。渲染进程将所有资源进行解析等处理后生成一张图片,最后再由浏览器内核显示图片。
安全沙箱
浏览器中的安全沙箱是利用操作系统提供的安全技术,让渲染进程在执行过程中无法访问或者修改操作系统中的数据。如果渲染进程需要访问系统资源,则需要通过浏览器内核获取系统资源后再通过 IPC 将结果返给渲染进程。安全沙箱最小的保护单位是进程,浏览器的多进程架构使得安全沙箱可以发挥作用。
由于渲染进程需要安全沙箱的保护,因此需要把在渲染进程内部涉及到和系统交互的功能都转移到浏览器内核中去实现。
安全沙箱对各个模块功能的影响:
1、持久存储
现代浏览器将读写文件的操作全部放在了浏览器内核中实现,然后通过 IPC 将操作结果转发给渲染进程。
1)存储 Cookie 数据的读写。通常浏览器内核会维护一个存放所有 Cookie 的 Cookie 数据库,渲染进程和浏览器内核通过 IPC 操作 Cookie 信息。
2)缓存文件的读写。
2、网络访问
渲染进程内部不能直接访问网络,需要通过浏览器内核来访问,并且浏览器内核在处理 URL 请求之前,会检查渲染进程是否有权限请求该 URL。
3、用户交互
渲染进程不能直接访问窗口句柄,都需要浏览器内核进行中转。
1)渲染进程需要渲染出位图,然后将位图发送到浏览器内核,由浏览器内核将位图显示到屏幕上
2)操作系统没有将用户输入事件直接传递给渲染进程,而是将这些事件传递给浏览器内核,然后浏览器内核再根据当前浏览器界面的状态来判断如何调度这些事件。如果焦点在浏览器地址栏中,那么输入事件会在浏览器内核中内部处理;如果焦点在内面区域,浏览器内核则会将输入事件转发给渲染进程处理。
站点隔离
站点隔离是指 Chrome 将同一站点(包含了相同根域名和相同协议的地址)中相互关联的页面放到同一个渲染进程中执行。如果多个不同站点中的内容通过 iframe 同时运行在同一个渲染进程中,黑客利用操作系统由处理器架构导致的的两个 A 级漏洞——幽灵(Spectre)和熔毁(Meltdown)可以直接入侵到进程的内部,甚至攻击操作系统。实现了站点隔离,就可以将恶意的 iframe 隔离在恶意进程内部,使得它无法继续访问其他 iframe 进程的内容,也就无法攻击其他站点。
网络安全
使用 HTTP 传输的内容很容易被中间人窃取、伪造和篡改,通常我们把这种攻击方式称为中间人攻击。鉴于 HTTP 的明文传输使得传输过程毫无安全性可言,可以在 TCP 和 HTTP 之间插入一个安全层,安全层有两个主要的职责:对发起 HTTP 请求的数据进行加密操作和对接收到 HTTP 的内容进行解密操作。
HTTPS
要使用加密,首先要在发送数据之前,浏览器和服务器要协商好加密方式和密钥,这个协商过程就是 HTTPS 建立安全连接的过程。
1、对称加密
所谓对称加密是指加密和解密都使用的是相同的密钥。服务器和客户端同时决定密钥过程:
1)浏览器发送自身所支持的加密套件(加密方法)列表和一个随机数 client-random;
2)服务器会从加密套件列表中选取一个加密套件,同时生成一个随机数 service-random,然后将两者一并返回给浏览器;
3)浏览器和服务器分别返回确认消息,然后它们再使用相同的方法将 client-random 和 service-random 混合起来生成一个密钥 master secret。
有了密钥 master secret 和加密套件之后,双方就可以进行数据的加密传输。但这里面有一个问题:传输 client-random 和 service-random 的过程是明文传输,而且随机数合成密钥的算法也是公开的,那么黑客截取到随机数就可以合成密钥进行一些恶意操作。
2、非对称加密
非对称加密算法有 A、B 两把密钥,如果你用 A 密钥来加密,那么只能使用 B 密钥来解密;反过来,如果你要 B 密钥来加密,那么只能用 A 密钥来解密。在 HTTPS 中,服务器会将其中的一个密钥通过明文的形式发送给浏览器,这个秘钥被称为公钥,服务器自己留下的那个密钥称为私钥。公钥是每个人都能获取到的,而私钥只有服务器才能知道。
非对称加密的请求流程:
1)浏览器发送加密套件列表给服务器;
2)服务器选择一个加密套件,然后将加密套件和公钥一道发送给浏览器;
3)浏览器和服务器返回确认消息。
浏览器获得公钥后,就可以在发送请求时使用公钥加密数据,然后服务器使用私钥进行解密。即使黑客获得了公钥,也无法解密加密了的数据,这样就保证了浏览器发送给服务器的数据是安全的。但非对称加密仍然有两个问题:
1)非对称加密的效率太低,加解密数据的速度太慢,影响用户体验;
2)无法保证服务器发给浏览器的数据安全,公钥是公开的,黑客得到公钥后即可对服务器使用私钥加密的数据进行解密。
3、对称加密和非对称加密搭配使用
在传输数据阶段依然使用对称加密,但是对称加密的密钥我们采用非对称加密来传输,这样可以解决非对称加密的两个问题。
混合加密的请求流程:
1)浏览器向服务器发送对称加密套件列表、非对称加密套件列表和随机数 client-random;
2)服务器保存随机数 client-random,选择对称加密和非对称加密的套件,并生成随机数 service-random,然后向浏览器发送选择的加密套件、service-random 和公钥;
3)浏览器保存公钥,并生成随机数 pre-master,利用公钥对 pre-master 加密,然后向服务器发送加密后的数据;
4)服务器拿出自己的私钥,解密出 pre-master 数据,并返回确认消息
5)服务器和浏览器就有了共同的 client-random、service-random 和 pre-master,两者会使用这三组随机数生成对称密钥,之后双方就可以使用该秘钥以对称加密的方式来传输数据
pre-master 是经过公钥加密之后传输的,黑客没有私钥也就无法拿到 pre-master 解密后的明文数据,那么也无法由三个随机数生成秘钥,这样就保证了传输过程中数据的安全性。但这仍然有个问题:如果原本访问正规网站,但是被黑客使用技术替换成黑客的网站,这样黑客就可以在自己的服务器上实现公钥和私钥,而浏览器是无法区分网站是否正规。此时,就需要一个权威机构发放一个证书来证明访问的服务器是正规的服务器。
4、添加数字证书
权威机构 CA(Certificate Authority)为服务器颁发数字证书(Digital Certificate)。数字证书有两个作用:
1)服务器通过证书证明自身的身份
2)数字证书中包含了服务器的公钥
含有数字证书的 HTTPS 的请求流程与混合加密的请求过程有两点区别
1)服务器没有直接返回公钥给浏览器,而是返回了包含公钥的数字证书
2)浏览器会先验证数字证书,证书验证通过之后才会继续后面的流程
证书是不能被伪造的,因此黑客伪造的站点是不可能通过证书验证的,也就没有后面截取数据的流程。
验证数字证书
使用 HTTPS 协议,浏览器就需要验证证书的合法性,最简单的方法是将 CA 证书内置在操作系统中。但这样内置所有 CA 机构证书是不现实的,因为 CA 机构很多。通常是根 CA(Root CAs) 给中间 CA(Intermediates CAs)做认证,中间 CA 又可以认证其他中间 CA,申请者则向这些中间 CA 去申请证书,就这样维护了一个可溯源的证书链。浏览器会使用中间 CA 证书验证用户得到的证书,再利用根证书来验证中间 CA 证书的合法性,最后浏览器会默认相信内置在系统中的根证书。如果黑客入侵系统,然后在系统中添加了恶意根证书,那么访问恶意的 HTTPS 网站也不会提示风险,也就是说 HTTPS 并非是绝对安全。盗版的操作系统也有可能内置恶意证书。