Chaper One 浏览器的安全
XSS攻击 (跨站脚本攻击)
基本概念:
- XSS即跨站脚本攻击,是一种代码注入攻击。
- 攻击者将恶意代码注入到目标网站,使其在用户的浏览器上执行。
- 从而盗取用户的cookie或者其它识别客户端身份的敏感信息
攻击类型:
存储型XSS
存储型XSS:恶意脚本存储在目标服务器上,当浏览器请求数据时,恶意脚本会从服务器端返回并执行。
攻击步骤:
- 攻击者将恶意代码提交到目标网站的数据库
- 用户打开目标网站时,服务器端将恶意代码从数据库取出,拼接到HTML返回给浏览器
- 用户浏览器接收到响应,对其解析并执行。混在其中的恶意代码也被执行。
- 恶意代码窃取用户数据并发送到攻击者网站;或冒充用户,与目标网站执行攻击者指定的操作
反射型XSS
反射型XSS:攻击者诱导用户去访问一个带有恶意代码的URL,服务器端接收请求后,返回带有恶意代码的数据到浏览器端,浏览器端解析这段带有XSS代码的数据并执行。
攻击步骤:
- 攻击者构造一个带有恶意代码的URL
- 用户在诱导下,访问这个URL。服务器端会将恶意代码从URL取出,拼接到HTML返回给浏览器
- 用户浏览器接收到响应,对其解析执行,混在其中的恶意代码也被执行
- 恶意代码窃取用户数据并发送到攻击者网站;或冒充用户,与目标网站执行攻击者指定的操作
注意,存储型XSS与反射型XSS的区别在于:存储型XSS的恶意代码是提交到目标网站的数据库;反射型XSS的恶意代码存储在构造好的URL当中
DOM型XSS
DOM型XSS:修改页面DOM节点形成的XSS
攻击步骤:
- 攻击者构造一个带有恶意代码的URL
- 用户打开这个带有恶意代码的URL;
- 用户浏览器接收到响应并执行,前端JS取出URL的恶意代码并执行;
- 恶意代码窃取用户数据并发送到攻击者网站;或冒充用户,与目标网站执行攻击者指定的操作
注意:取出和执行恶意代码都是浏览器端完成,属于前端JS的漏洞;存储型和反射型则属于服务器端的漏洞
防范XSS
① cookie设置httpOnly ,使得脚本无法获取cookie
cookie.setHttpOnly(true);
② 使用验证码,使攻击者无法伪装成用户身份
③ 使用白名单过滤 ,列出合法可出现的字符,对输入进行验证过滤,则可避免可能导致XSS攻击的字符
④ 转义HTML ,XSS攻击能实现是因为 输入的内容变成可执行代码,对HTML进行转义,譬如 < 变成 &alt
⑤ 避免使用innerHTML
CSRF攻击(跨站请求伪造)
CSRF的攻击流程:
- WebA是User信任的网站,User登录WebA
- 登录验证后,WebA返回Cookie等信息返回给User,并保存在浏览器本地
- User在没有退出WebA的情况下,又去访问危险网站WebB
- WebB接收到User的请求,服务器返回了恶意代码。恶意代码执行,发出要访问WebA的请求
- 浏览器带着还保存在浏览器本地的cookie,去访问了WebA
- WebA无法访问该请求是否为用户本人操作。因为Cookie已经被盗用了,WebB有了User的身份。
我们无法保证:
- 登录一个网站后,不会再访问另外一个网站
- 本地的cookie能在访问另外一个网站时就过期失效
- 危险网站WebB可能是我们信任但却出现了安全漏洞的网站
常见的CSRF攻击类型有:
GET类型
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
- 通常是,危险网站中含有img标签;
- 当用户访问页面时,浏览器就会自动向img的src地址发送一次HTTP请求
POST类型
<form action="http://bank.example/withdraw" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
- 通常利用的是自动提交的表单,这个表单在页面中被隐藏
- 当用户访问页面时,表单自动提交,模拟用户发送一次POST请求
链接类型
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
重磅消息!!
<a/>
- 通常是利用一些图片、夸张性广告诱导用户点击链接
- 用户点击后,则会发起请求。
防范CSRF
CSRF的本质是:攻击者利用User尚保存在浏览器本地的Cookie信息,冒充User身份,向网站发送请求。
- 进行同源检测:服务器根据http请求头中的refer和origin字段来判断,该请求是否来自允许访问的站点。
- 使用Token:服务器向用户返回一个随机数 Token ,当网站再次发起请求时,在请求参数中加入服务器端返回的 token ,然后服务器对这个 token 进行验证。这种方法解决了使用 cookie 单一验证方式时,可能会被冒用的问题。这种方法存在一个缺点就是,我们需要给网站中的所有请求都添加上这个 token,操作比较繁琐。还有一个问题是一般不会只有一台网站服务器,如果请求经过负载平衡转移到了其他的服务器,但是这个服务器的 session 中没有保留这个 token 的话,就没有办法验证了。
中间人攻击 ***
前端方面的安全问题
- XSS
- CSRF
- Iframe滥用
- 恶意的第三方库:?论是后端服务器应?还是前端应?开发,绝?多数时候都是在借助开发框架和各种类库进?快速开发,?旦第三?库被植?恶意代码很容易引起安全问题。
网络劫持 (DNS劫持和HTTP劫持)
网络劫持分 DNS劫持 和 HTTP劫持
DNS劫持 (访问A却强制访问到A+(可能带有广告))
- 用户在浏览器输入网站的域名,需要靠DNS(域名系统)去解析域名,返回计算机能够识别的IP地址。通过访问IP地址,从而访问到目标网站
- 那么DNS劫持则是,返回的并不是目标网站的IP地址,而是一个中间服务器的IP地址。
- 访问中间服务器的IP地址,会一致性返回302,让用户跳转到带有广告的网页。该网页再通过iframe引入原来目标网页的内容
HTTP劫持 (访问A,而A一直有附加广告)
- 在TCP连接中,找出并标记应用层采用的是HTTP协议的连接
- 篡改HTTP响应体,对数据包内容进行篡改
- 抢先回包,将篡改后的数据包抢先正常站点返回的数据包先到达用户侧,正常的数据包则会被丢弃。
HTTP劫持的防范:
- 采用HTTPS (性能降低)
- 拆分HTTP请求,躲过标记
-----------------------------------
Chaper Two 浏览器的组成
对浏览器的理解
浏览器的主要功能:
- 用户通过URI,即统一资源标识符,指定所请求资源的位置。
- 浏览器则向服务器发送请求,并将用户指定的web资源呈现到浏览器窗口。
- web资源的格式通常是HTML,也包括pdf,image等其它格式
浏览器的组成分为两部分:shell和内核。其中shell的种类比较多,内核则比较少。
- shell:指的是浏览器的外壳,例如菜单、工具栏等;shell通过调用内核,为用户提供各种界面操作和参数设置。
- 内核:是浏览器的核心。
对浏览器内核的理解
浏览器的内核分作两部分:
渲染引擎 主要用于渲染,有三个职责,最终将内容输出显示到显示器或打印机
- 获取页面的内容(HTML、XML、Image)
- 处理讯息
- 计算页面的显示方式
JavaScript引擎
- 解析、执行JavaScript,从而实现页面的动态效果
常见浏览器所用的内核
- IE浏览器:Trident内核
- Chrome浏览器:以前是webkit内核,现在是Blink内核
- Firefox浏览器:Gecko内核
- safari浏览器:webkit内核
- Opera浏览器:Presto内核 -> webkit内核 -> Blink内核
浏览器的组成部分
- 用户界面:地址栏、前进/后退按钮、书签菜单等
- 浏览器引擎:在用户界面与呈现引擎之间传输指令
- 呈现引擎:显示请求的内容
- 用户界面后端
- JavaScript解释器
- 数据存储:如cookie
- 网络
-----------------------------------
Chaper Three 浏览器的渲染
浏览器的渲染过程
- 解析文档(HTML、XHTML、SVG),生成 DOM Tree
- 解析CSS,生成 CSSOM Rule Tree
- 根据DOM Tree和CSSOM Rule Tree,生成 Rendering Tree 渲染树。渲染树的节点称作渲染对象,渲染对象与DOM对象不是一一对应的。
- 布局:生成Rendering Tree渲染树后,弄清楚渲染树各个节点的大小和确切位置,进行布局(自动重排)
- 绘制:遍历渲染树,调用paint方法,将内容绘制显示到屏幕上。
浏览器的渲染优化
① JavaScript会阻塞HTML和CSS的解析,从而阻缓页面的渲染
- 将JS文件尽量放在body的后面,不要放在开头或穿插在中间
- 尽量使用async或defer属性,使得script能够被异步加载,从而不会停止文档的解析
② CSS方面的优化
- 内联首屏关键CSS,使得GUI直接渲染,减少渲染时间
- 减少重排重绘
- 如果需要引入外部CSS文件,尽量使用link而不是@import:link会产生一个新线程去加载CSS资源,不阻塞GUI渲染线程继续渲染代码;@import则会暂停GUI渲染线程,先去加载CSS资源,从而阻塞了页面渲染
- CSS选择器应当精简,避免冗杂无用的遍历,避免重复书写CSS代码
③ HTML —— DOM Tree的构建
CSS阻塞文档的解析
浏览器的解析,分为三方面
- 解析文档(HTML、XHTML、SVG),生成 DOM Tree
- 解析CSS,生成 CSSOM Rule Tree
- 解析JavaScript,通过 DOM API 和 CSSOM API 操作 DOM Tree 和 CSSOM Rule Tree
CSS阻塞文档的解析的原因分析:
- JavaScript可能在文档解析过程中,请求样式信息。
- 若CSS还未解析完成,即CSSOM Rule Tree还未构建完成,那JS则会得到错误的值,显然不合理。
- 所以,如果在CSS未解析完毕,而JS又想操作CSSOM Rule Tree的情况下,会先加载解析CSS,完成对CSSOM Rule Tree 的构建,再执行JavaScript,最后恢复对DOM Tree的构建。
JS文件阻塞文档的解析
JS文件会阻塞文档的解析:
- 停止对文档的解析,停止构建DOM Tree
- 将控制权交给JavaScript引擎
- 待JS加载、解析、执行完毕后,再恢复对文档的解析
渲染页面时的常见不良现象(FOUC、白屏)
- FOUC:主要指的是样式闪烁的问题。即CSS加载之前,先加载了HTML,则出现了“先展示无样式内容,然后再突然呈现样式”的现象。原因是:CSS加载时间过长、CSS放在文档底部
- 白屏:浏览器迟迟未渲染页面。有的浏览器需要先构建DOM树和CSSOM树,构建完成再渲染。有可能因为CSS放在HTML尾部,CSS未加载完成,则就不能构建完成,从而不能渲染而白屏;也有可能是JS放在了头部,阻塞了DOM的解析。
文档的预解析
预解析:
- 文档的预解析是浏览器内核对解析过程的优化
- 当执行JavaScript脚本时,另外一个线程解析剩下的文档,并加载后面需要通过网络请求的资源,从而加快了解析速度
- 文档的预解析不会改变DOM Tree,DOM Tree的构建是主线程的任务。
优化关键渲染路径
尽快完成首次渲染,需要最大限度减小以下三个因素:
关键资源:指的是可以阻塞页面首次渲染的资源,如JavaScript,CSS等。关键资源数量越少,浏览器的渲染工作量越少,CPU的占用也就越小。
关键路径:关键路径的长度指的是关键渲染路径的总耗时。
关键字节:关键字节的大小指的是关键资源的字节大小。关键资源的字节越小,那么下载速度就越快。
有如下几个方面可以优化:
一、优化DOM
- 缩小文档的尺寸、使用gzip压缩、使用缓存
- 优化DOM则是尽可能减小关键路径的长度和关键字节的大小
二、优化CSSOM
同优化CSS
三、异步加载JavaScript
-----------------------------------
Chaper Four 浏览器的存储
Cookie
Cookie的原理:
- 用户首次访问网页时,服务器并不清楚用户信息。服务器返回一些数据即Cookie给客户端浏览器,并保存在浏览器/本地。
- 当用户发送第二次HTTP请求时,直接把上次HTTP请求返回且保存到浏览器/本地的Cookie交给服务器端。那么服务器端通过Cookie就能判断用户的身份。
Cookie的特点:
- 只能存储简单的字符串类型;
- 保存在浏览器/本地,在每次同源请求下都会携带Cookie访问服务器端
- 单个Cookie不能超过4K,多数浏览器限制一个站点不能超过20个Cookie,一个浏览器最多创建300个Cookie
- Cookie无法跨域
- Cookie的安全性并不高
Cookie的缺陷:
- Cookie安全性并不高
- Cookie的大小受限
- 浏览器可以禁用Cookie
Cookie有哪些字段
- Name : Cookie的名称
- Value:Cookie的值
- Size:Cookie的大小
Expires/Max-Age
- Expires:指定一个具体的到期时间,过了这个时间,Cookie则失效。Expires是UTC格式,可以使用Date.prototype.toUTCString()转换
- Max-Age:指定从现在开始Cookie 可以存在的秒数。
注意:
- Max-Age的优先级比Expires要高
- 如果没有设置Expires和Max-Age,那么就是Session-Cookie(会话Cookie)。也就是生命周期为会话周期,一旦关闭浏览器Cookie则失效。
Secure/HttpOnly
- Secure:指定浏览器只有在HTTPS下,才能传送这个Cookie
- HttpOnly:指定不能通过JavaScript脚本读取Cookie,只有浏览器发出Http请求时,才会带上Cookie
Domain/path
- Domain 设置了可以访问该Cookie的域名,path则设置可以访问该Cookie的页面路径;
- Domain和path的设置,决定了只有访问什么域名/路径才会带上Cookie
JS如何操作Cookie、WebStorage ***
Cookie和WebStorage的区别
- 存储类型:都是存储简单的字符串类型
- 存储地方:都保存在客户端浏览器;但Cookie在每次同源请求会与服务器端通信,sessionStorage和localStorage不会与服务器端通信
- 存储大小:单个Cookie不能超过4KB;sessionStorage和localStorage不能超过5MB
- 生命周期:Cookie有一个Expire值,超过则失效;sessionStorage是在当前会话下有效;localStorage除非手动清除,否则永久存在
- 作用域:Cookie和localStorage是在同源页面下有效;sessionStorage只能被同一个窗口的同源页面所共享。
Cookie和Session的区别
- 存储类型:Cookie只能存储字符串类型;Session可以存储任意类型对象;
- 存储地方:Cookie存储在浏览器/本地;Session存储在服务器端
- 存储大小:单个Cookie不能超过4K,多数浏览器限制一个站点不能超过20个Cookie;Session没有大小限制,可存储的数据大小与服务器的内存有关
- 安全性:session的安全性更高
- 性能:session保存在服务器端,当访问增多时,增加服务器的压力
IndexedDB ***
单点登录 ***
-----------------------------------
Chaper Five 进程与线程
进程与线程的概念
进程:
- 是资源分配的最小单位,能拥有资源和独立运行的最小单位
- 描述了CPU在运行指令及加载保存上下文所需的时间
- 是一个程序的运行实例:当启动一个程序时,操作系统会为该程序分配一块内存,用于存放代码、运行中的数据和一个执行任务的主线程
- 运行在虚拟内存上(虚拟内存用于解决用户对硬件资源的无限需求和有限的硬件资源之间的矛盾)
- 一个进程中可以有多个线程
线程:
- 是CPU调度的最小单位
- 描述了执行一段指令所需的时间
进程与线程的区别
- 进程是资源分配的最小单位(能拥有资源和独立运行的最小单位);线程是CPU调度的最小单位(一个进程中有多个线程)
- 进程之间通信需要借助进程通信;线程之间可以直接共享同一进程中的资源
- 进程切换比线程切换的开销要大(线程是CPU调度的最小单位)
- 进程的创建、撤销要比线程的开销要大(系统都要为其分配或回收资源)
进程之间的通信方式
产生死锁的原因
实现浏览器内多个标签页之间的通信
浏览器渲染进程的线程有哪些
僵尸进程和孤儿进程
|