前端开发必须掌握的浏览器安全知识

3,349 阅读14分钟

浏览器安全主要划分为三大块内容:页面安全、系统安全和网络安全。以下内容(XSS,CSRF,浏览器安全沙箱,HTTPS)是我近期所学和复习的一些内容,仅作为个人学习记录,如有不对还望多包涵和指正。

一、XSS

XSS 全称是 Cross Site Scripting,为了与“CSS”区分开来,故简称 XSS,翻译过来就是“跨站脚本”。XSS 攻击是指黑客往 HTML 文件中或者 DOM 中注入恶意脚本,从而在用户浏览页面时利用注入的恶意脚本对用户实施攻击的一种手段。

存储型 XSS 攻击

存储型 XSS 攻击大致需要经过如下步骤:
1首先黑客利用站点漏洞将一段恶意 JavaScript 代码提交到网站的数据库中;
2然后用户向网站请求包含了恶意 JavaScript 脚本的页面;
3当用户浏览该页面的时候,恶意脚本就会将用户的 Cookie 信息等数据上传到服务器。

反射型 XSS 攻击

恶意 JavaScript 脚本属于用户发送给网站请求中的一部分,随后网站又把恶意 JavaScript 脚本返回给用户。当恶意 JavaScript 脚本在用户页面中被执行时,黑客就可以利用该脚本做一些恶意操作。

比如我把一个恶意脚本卸载链接后面,发到网站上,别人点了这个链接进去就会触发恶意脚本。

Web 服务器不会存储反射型 XSS 攻击的恶意脚本,这是和存储型 XSS 攻击不同的地方。

基于 DOM 的 XSS 攻击

黑客通过各种手段将恶意脚本注入用户的页面中,比如通过网络劫持在页面传输过程中修改 HTML 页面的内容,这种劫持类型很多,有通过 WiFi 路由器劫持的,有通过本地恶意软件来劫持的,它们的共同点是在 Web 资源传输过程或者在用户使用页面的过程中修改 Web 页面的数据。

解决办法:

  1. 不要相信用户的任何输入,对用户输入内容进行检查、过滤和转义。
  2. HttpOnly HttpOnly 是服务器通过 HTTP 响应头来设置的,使用 HttpOnly 标记的 Cookie 只能使用在 HTTP 请求过程中,所以无法通过 JavaScript 来读取这段 Cookie。

二、CSRF

跨站请求伪造,CSRF 攻击是攻击者借助受害者的 Cookie 骗取服务器的信任,可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击服务器,从而在并未授权的情况下执行在权限保护之下的操作。

一个疑问:受浏览器同源政策影响,在另一个伪造网址发送请求,为什么能到正规网站返回给用户的session。 如果是CSRF攻击,那么黑客是拿不到受害者站点数据的。但是黑客会在他的A站点中调用受害者B站点的http接口,这些接口可以是转账,删帖或者设置等。这个过程中你需要注意一点,在黑客A站点中调用受害者B站点的http接口时,默认情况下,浏览器依然会把受害者的Cookie等信息数据发送到受害者的B站点,【注意这里并不是黑客的A站点】。如果B站点存在漏洞的话,那么黑客就会攻击成功,比如将受害者的金币转出去了!

解决办法:

  1. Cookie 的 SameSite 属性。在 HTTP 响应头中,通过 set-cookie 字段设置 Cookie 时,可以带上 SameSite 选项,如下:
set-cookie: 1P_JAR=2019-10-20-06; expires=Tue, 19-Nov-2019 06:36:21 GMT; path=/; domain=.google.com; SameSite=none

SameSite 选项通常有 Strict、Lax 和 None 三个值。
Strict 最为严格。如果 SameSite 的值是 Strict,那么浏览器会完全禁止第三方 Cookie。简言之,如果你从极客时间的页面中访问 InfoQ 的资源,而 InfoQ 的某些 Cookie 设置了 SameSite Strict 的话,那么这些 Cookie 是不会被发送到 InfoQ 的服务器上的。只有你从 InfoQ 的站点去请求 InfoQ 的资源时,才会带上这些 Cookie。
Lax 相对宽松一点。在跨站点的情况下,从第三方站点的链接打开和从第三方站点提交 Get 方式的表单这两种方式都会携带 Cookie。但如果在第三方站点中使用 Post 方法,或者通过 img、iframe 等标签加载的 URL,这些场景都不会携带 Cookie。
而如果使用 None 的话,在任何情况下都会发送 Cookie 数据。

  1. 验证请求的来源站点
    由服务器端验证当前请求的来源站点,HTTP 请求头中的 Referer 和 Origin 属性

Origin 属性只包含了域名信息,并没有包含具体的 URL 路径,这是 Origin 和 Referer 的一个主要区别。

  1. CSRF Token

第一步,在浏览器向服务器发起请求时,服务器生成一个 CSRF Token,存到前端。

第二步,在浏览器端如果要发起转账的请求或敏感操作时,那么需要带上页面中的 CSRF Token,然后服务器会验证该 Token 是否合法。如果是从第三方站点发出的请求,那么将无法获取到 CSRF Token 的值,所以即使发出了请求,服务器也会因为 CSRF Token 不正确而拒绝请求。

三、安全沙箱

设计现代浏览器体系架构时,将浏览器划分为不同的进程是为了增加其稳定性。虽然设计成了多进程架构,不过这些模块之间的沟通方式却有些复杂,也许你还有以下问题:

1为什么一定要通过浏览器内核去请求资源,再将数据转发给渲染进程,而不直接从进程内部去请求网络资源?

2为什么渲染进程只负责生成页面图片,生成图片还要经过 IPC 通知浏览器内核模块,然后让浏览器内核去负责展示图片?

通过以上方式不是增加了工程的复杂度吗?

首先现在的浏览器内核被划分为浏览器内核和渲染内核两个核心模块,浏览器内核包含了网络线程、GPU进程、浏览器进程。 所有的与系统相关的操作或者id操作都是在浏览器内核中进行的,例如(cookie存储、cache存储、文件下载、文件读取、网络请求等),而渲染内核中的渲染进程做哪些?(html、css解析、js、布局、绘制)。

安全沙箱最小的保护单位是进程,所以被安全沙箱保护的进程就是渲染进程。在网络上你下载一个恶意程序,如果你不去执行他是不会有任何影响的,只有你去执行了才会有破坏,而浏览器中执行的这一步就是渲染进程去做的。

站点隔离(Site Isolation)

所谓站点隔离是指 Chrome 将同一站点(包含了相同根域名和相同协议的地址)中相互关联的页面放到同一个渲染进程中执行。

最开始 Chrome 划分渲染进程是以标签页为单位,也就是说整个标签页会被划分给某个渲染进程。但是,按照标签页划分渲染进程存在一些问题,原因就是一个标签页中可能包含了多个 iframe,而这些 iframe 又有可能来自于不同的站点,这就导致了多个不同站点中的内容通过 iframe 同时运行在同一个渲染进程中。

比如一个网站有ABC三个iframe,其中a Iframe存在漏洞问题或者恶意程序,但是此时他们在一个渲染进程中,就有可能会对其他网站造成影响。因为沙箱隔离当前情况下只针对渲染进程,而他们却都在一个渲染进程下。

实现了站点隔离,就可以将恶意的 iframe 隔离在恶意进程内部,使得它无法继续访问其他 iframe 进程的内容,因此也就无法攻击其他站点了。

四、HTTPS

从 HTTP 协议栈层面来看,HTTP->TCP->IP>数据链路层,而HTTPS 实际上就是在HTTP和TCP中插入了一个安全层, HTTP->安全层(SSL/TLS)->TCP->IP>数据链路层. 安全层所做的事情就2件:对发起的http请求进行加密,对接受到的http内容进行解密。

第一版:对称加密

  1. 首先浏览器向服务器发送一个加密套件列表和随机数client-random。这里的加密套件是指加密的方法,加密套件列表就是指浏览器能支持多少种加密方法列表。
  2. 服务器接收到后,选择一个加密套件,然后也生成一个随机数service-random,然后把这些东西返回给浏览器。
  3. 此时浏览器和服务器都有了指定的加密套件和各自的随机数,使用相同的加密方法将client-random和service-random生成密钥,然后发送的内容都用密钥加密和解密。

问题:浏览器和服务器在首次交换加密套件和随机数的时候是明文的,这个过程被截获的话,黑客同样能生成相对应的密钥。

第二版:非对称加密

  1. 首先还是浏览器发送加密套件列表给服务器
  2. 服务器接受到后将加密套件和一个公钥返回给浏览器,浏览器自己存有私钥。
  3. 之后浏览器就用公钥加密,传给浏览器,服务器用私钥解密。然后返回的信息服务器用私钥加密,传给浏览器,浏览器用公钥解密,完成信息的交换。 因为私钥只存在服务器端,黑客即使拿到数据也没办法解密。

问题:
1黑客确实没办法解密浏览器端用公钥加密的信息,但是他可以在最开始明文交换密钥的时候拿到公钥,那他就可以解密服务器端用私钥加密的信息。
2非对称加密的效率太低了,这会严重影响到加解密数据的速度,进而影响到用户打开页面的速度。

第三版:对称加密和非对称加密搭配使用

  1. 首先浏览器生成随机数client-random,向服务器发送对称加密套件列表、非对称加密套间列表和client-random。
  2. 服务器接收到以上信息后,生成service-random,选择一个对称加密套间和非对称加密套间(生成公钥和私钥),将service-random、公钥、对称加密套间这些信息发回给浏览器。
  3. 浏览器保存拿到的公钥,再生成一个随机数pre-master,用公钥加密这个pre-master,将加密的信息发送给服务器。
  4. 服务器用私钥解密出pre-master信息。 此时服务器端和浏览器端都具有三个随机数client-random、service-random、pre-master,利用这个三个随机数信息和指定的对称加密算法进行生成对称密钥,之后就用这个对称密钥进行信息的加解密。 (黑客可以截获pre-master,但他无法解密,因为他没有私钥)

简单来说就是在传输数据阶段依然使用对称加密,但是对称加密的密钥我们采用非对称加密来传输。用非对称加密进行对称加密时的密钥交换,是其不以明文的形式暴露。

问题:
是黑客通过 DNS 劫持将极客时间官网的 IP 地址替换成了黑客的 IP 地址,这样我访问的其实是黑客的服务器了,黑客就可以在自己的服务器上实现公钥和私钥,而对浏览器来说,它完全不知道现在访问的是个黑客的站点。所以问题了来了,我怎么证明我是我?

第四版:数字证书

网站管理员向CA 机构进行申请,提交自己的公钥还有网站的信息包括网站域名、有效时长等,CA机构根据这些信息制作证书,然后将这个证书用自己的私钥加密,将加密的结果返回给网站管理员。

此时当浏览器访问服务器的时候,服务器会把这个证书返给浏览器,浏览器会验证这个数字证书的真实性,如何证书是合法的,会再去验证这个CA机构是不是合法的,通常情况下,操作系统中会内置信任的顶级 CA 的证书信息(包含公钥),如果这个 CA 链中没有找到浏览器内置的顶级的 CA,证书也会被判定非法。验证完毕都是正常的,那证明这个网站是真的,而不是他人伪造的。

这个主要流程和第三版的区别不大,主要改变点在2个:

1服务器没有直接返回公钥给浏览器,而是返回了数字证书,而公钥正是包含在数字证书中的; 2在浏览器端多了一个证书验证的操作,验证了证书之后,才继续后续流程。

浏览器如何验证数字证书

浏览器接收到数字证书之后,会对数字证书进行验证。首先浏览器读取证书中相关的明文信息,采用 CA 签名时相同的 Hash 函数来计算并得到信息摘要 A;然后再利用对应 CA 的公钥解密签名数据,得到信息摘要 B;对比信息摘要 A 和信息摘要 B,如果一致,则可以确认证书是合法的。

浏览器如何验证CA机构合法性

全球就有很多家CA机构,然后就出现了一个问题,这些CA是怎么证明它自己是安全的?如果一个恶意的公司也成立了一个CA机构,然后给自己颁发证书,那么这就非常危险了,因此我们必须还要实现一个机制,让CA证明它自己是安全无公害的。

这就涉及到数字证书链了。

要讲数字证书链,就要了解我们的CA机构也是分两种类型的,中间CA(Intermediates CAs)和根CA(Root CAs),通常申请者都是向中间CA去申请证书的,而根CA作用就是给中间CA做认证,通常,一个根CA会认证很多中间的CA,而这些中间CA又可以去认证其它的中间CA。

比如你可以在Chrome上打开某个网站,然后点击地址栏前面的那把小锁,你就可以看到*.geekbang,org的证书是由中间CA GeoTrust RSA CA2018颁发的,而中间CA GeoTrust RSA CA2018又是由根CA DigiCert Global Root CA颁发的,所以这个证书链就是:*.geekbang,org--->GeoTrust RSA CA2018-->DigiCert Global Root CA。

因此浏览器验证证书时,会先验证*.geekbang,org的证书,如果合法在验证中间CA的证书,如果中间CA也是合法的,那么浏览器会继续验证这个中间CA的根证书。

这时候问题又来了,怎么证明根证书是合法的?

浏览器的做法很简单,它会查找系统的根证书,如果这个根证书在操作系统里面,那么浏览器就认为这个根证书是合法的,如果验证的根证书不在操作系统里面,那么就是不合法的。

而操作系统里面这些内置的根证书也不是随便内置的,这些根CA都是通过WebTrust国际安全审计认证。

那么什么又是WebTrust认证?

WebTrust(网络信任)认证是电子认证服务行业中唯一的国际性认证标准,主要对互联网服务商的系统及业务运作的商业惯例和信息隐私,交易完整性和安全性。WebTrust认证是各大主流的浏览器、微软等大厂商支持的标准,是规范CA机构运营服务的国际标准。在浏览器厂商根证书植入项目中,必要的条件就是要通过WebTrust认证,才能实现浏览器与数字证书的无缝嵌入。

目前通过WebTrust认证的根CA有 Comodo,geotrust,rapidssl,symantec,thawte,digicert等。也就是说,这些根CA机构的根证书都内置在个大操作系统中,只要能从数字证书链往上追溯到这几个根证书,浏览器会认为使用者的证书是合法的