参考博文:
前端安全-常见的攻击以及防御
前端的安全问题
前端安全系列(一):如何防止XSS攻击?
前端安全系列之二:如何防止CSRF攻击?
以下是简单总结:
1、CSRF攻击(跨站请求伪造)
(1) 攻击流程:
- 用户访问a.com,并保留登录凭证(cookie)
- 攻击者引诱受害者访问b.com
- b.com向a.com发送一个请求,浏览器会默认携带a.com的cookie
- a.com接收到请求之后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求
- a.com以受害者的名义,执行了b.com发送的请求
- 攻击完成
(2) 攻击类型
- Get类型:只需要一个简单的HTTP请求
- POST类型:使用一个自动提交的表单
- 链接类型:
(3) CSRF特点
- CSRF(通常)发生在第三方域名
- CSRF不能获取到Cookie等信息,只是使用
(4) 防护策略
- 阻止不明外域的访问
- 同源检测
- Samesite Cookie - 提交时要求附加本域才能获得的信息
- CSRF Token
- 双重Cookie验证
(5) 各个策略介绍
- 同源检测
- 使用Origin Header确定来源域名
- 使用Referer Header 确定来源域名
- Samesite Cookie:在Set-Cookie中新增Samesite属性
- Samesite = Strict :表明这个Cookie任何情况下都不可能作为第三方Cookie
- Samesite = Lax:宽松模式:假如这个请求是这种请求(改变了当前页面或者打开了新页面)且同时是个GET请求,则这个Cookie可以作为第三方Cookie
- CSRF Token:用户打开页面时,服务器给这个用户生成呢个一个Token
- 将Token存放在服务器的Session中,之后每次页面加载时,使用js遍历整个DOM树,对于DOM中生成的所有a和form标签加入Token
- 页面提交的请求携带这个Token
- 服务器验证这个Token是否正确
- 双重Cookie
- 用户访问网站时,向请求域名注入一个Cookie,内容为随机字符串
- 在前端向后端发起请求时,取出Cookie,并添加到URL的参数中
- 后端接口验证Cookie中的字段与URL参数中的字段是否一致,不一致则拒绝
2、XSS攻击(跨站脚本攻击)
(1) 攻击方式
XSS,攻击者通过在目标网站注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可以获取用户的敏感信息如Cookie、SessionID等。注入方式有:
- 在HTML中内嵌的文本中,恶意内容以script标签形成注入
- 在标签的href src等属性中,包含javascript: 等可执行代码
- 在onload\onerror\onclick等事件中注入不受控制的代码
等等
(2) XSS分类
- 存储型XSS
- 存储区:(恶意代码存放的位置)后端数据库
- 插入点:(由谁取得恶意代码,并插入到网页上)HTML
- 反射型XSS
- 存储区:URL
- 插入点:HTML
- DOM型XSS
- 存储区:后端数据库/前端存储/URL
- 插入点:前端Javascript
(3) 攻击步骤
- 存储型XSS
- 攻击者将恶意代码提交到目标网站的数据库中
- 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作
- 反射型XSS
- 攻击者构造出特殊的 URL,其中包含恶意代码
- 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作
- DOM型XSS
- 攻击者构造出特殊的 URL,其中包含恶意代码
- 用户打开带有恶意代码的 URL
- 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作
三者区别:DOM型XSS攻击,取出和执行恶意代码由浏览器端完成,属于前端js自身安全的漏洞;其他两种XSS都属于服务端自身的安全漏洞
(4) 防御策略
- 防止HTML中出现注入
- 防止javascript执行时,执行恶意代码
(5) 防御步骤
-
预防存储型和反射型XSS
- 改成纯前端渲染,把代码和数据分隔开
- 浏览器先加载一个静态 HTML,此 HTML 中不包含任何跟业务相关的数据
- 然后浏览器执行 HTML 中的 JavaScript
- JavaScript 通过 Ajax 加载业务数据,调用 DOM API 更新到页面上
- 对HTML做充分转义
- 改成纯前端渲染,把代码和数据分隔开
-
预防DOM型XSS
- 在使用 .innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent、.setAttribute() 等
- 如果用 Vue/React 技术栈,并且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 阶段避免 innerHTML、outerHTML 的 XSS 隐患
- DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等, 标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,如果项目中有用到这些的话,一定要避免在字符串中拼接不可信数据。