前端安全--攻与防

743 阅读22分钟

声明:本章内容大部分来自对互联网信息的整理,小部分自己写的,感谢原作者的奉献。由于时间有点久,且内容来源比较庞杂,故无法将引用来源一一列举,如果有引用到您的内容,请私信,我将会在文章之中关联或者做删除处理。本文为内部技术分享内容,现在分享给大家!

image.png

DOS攻击

攻击原理

DOS攻击通过在网站的各个环节进行攻击,使得整个流程跑不起来,以达到瘫痪服务为目的。最常见的就是发送大量请求导致服务器过载宕机

防范措施

  • 扩容服务器【有钱公司玩的】
  • 上高防云服务器【主打一个贵】
  • 进行实时监控,封禁某些恶意密集型请求IP段
  • 增加接口验证,对于某些敏感接口,进行单个IP访问次数限制
  • 进行静态资源缓存,隔离源文件的访问,比如CDN加速

CSRF-跨站请求伪造

什么是CSRF攻击?

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

CSRF的危害有哪些?

攻击者盗用了你身份,以你的名义发送恶意请求,CSRF能够做的事情:以你的名义发送邮件,盗取你的账号甚至是购买商品,虚拟货币的转账,个人隐私泄露和财产安全

CSRF攻击类型及原理

攻击者构造出一个后端请求地址,诱导用户点击或者通过某些途径自动发起请求。如果用户是在登录状态下的话,后端就以为是用户在操作,从而进行相应的逻辑。

主动攻击型

  • 受害者访问a.com并在自己浏览器留下a.com的登录态(比如cookie)
  • 攻击者诱导受害者访问网站b.com
  • 网站b.com植有访问a.com接口的恶意代码(删除/增加/修改等),浏览器请求头中会默认携带 a.com 网站的cookie
  • 受害者点击b.com时候,b.com带着a.com的登陆凭证冒充受害用户执行对a.com的恶意操作

被动攻击型

1、攻击者在a.com发布带有恶意链接的帖子或者评论(提交对a.com带有增删改的诱导型img/form/a标签)
2、当其他拥有登录态的受害者点击该评论的恶意链接冒用受害者登录凭证发起攻击
3、CSRF主要是冒用受害者登录凭证发起恶意的增删改并不会窃取受害者隐私信息
4、常见的CSRF攻击类型

GET类型的CSRF

GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用

image.png

在受害者访问含有这个img的页面后,浏览器会自动向bank.example/withdraw?ac…

POST类型的CSRF

这种类型的CSRF利用起来通常使用的是一个自动提交的表单,如:
image.png 访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。
POST类型的攻击通常比GET要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许POST上面

POST类型攻击特点
  • 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
  • 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
  • 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
  • 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。

CSRF防范措施

禁止三方网站获取cookie,比如设置Chrome的SameSite属性

  • Samesite=Strict,这种称为严格模式,表明这个 Cookie 在任何情况下都不可能作为第三方 Cookie
  • Samesite=Lax,这种称为宽松模式,比 Strict 放宽了点限制:假如这个请求是这种请求(改变了当前页面或者打开了新页面)且同时是个GET请求,则这个Cookie可以作为第三方Cookie。(默认)
  • None 任何情况下都会携带;
    弊端:SameSite试用阶段,兼容性不是很理想

服务端通过Referer Header 和 Origin Header来进行同源验证

  • 弊端1:攻击者可以部分修改或者隐藏referer
  • 弊端2: 某些浏览器或者操作会丢失origin头部,比如302重定向
  • 弊端3:HTTPS页面跳转到HTTP页面,所有浏览器Referer都丢失。
  • 弊端4:对于被动性攻击并不能识别
  • 其他: 某些低版本浏览器对origin和referer并不是很稳定,各种意想不到的结果,极其不稳定

利用token来鉴别,三方跨站请求并不能获取到头部的token,本站的接口在请求前都会在请求头增加token用于身份鉴权,三方请求并不会携带token

弊端1:token鉴权对服务端压力较大,许专门开辟服务器用于token鉴权,耗费服务器成本并且增加请求时间
弊端2:对于页面ajax,fetch等异步请求外的其他请求如form提交,a链接等需要去挨个加token,不能形成统一的token增加入口,存在部分疏漏。相对而言token鉴权算是比较好的一种防护措施

利用双重cookie来认证,在每个请求的参数都附加scrfCookie='随机数'防御参数,并在cookie中混入该防御参数值,服务端将请求头部的cookie中防御cookie参数和请求参数所带的该参数进行比对

弊端: 前后分离的代码,后端接口和前端可能不同源,比如前端www.xx.com,后端接口为api.xx.com,前端要拿到后端接口域下的cookie必须将cookie都放在xx.com下面才能保证所有子域都可以拿到,这样反而增加xss攻击风险得不偿失

XSS-跨站脚本攻击

什么是跨站脚本攻击?

Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。为了和 CSS 区分,这里把攻击的第一个字母改成了 X,于是叫做 XSS。

XSS攻击有哪些危害?

危害

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马
7、控制受害者机器向其它网站发起攻击

案例

(1)2005年,年仅19岁的 Samy Kamkar 发起了对 MySpace.com 的 XSS Worm 攻击。 Samy Kamkar 的蠕虫在短短几小时内就感染了100万用户——它在每个用户的自我简介后边加了一句话:“but most of all, Samy is my hero.”(Samy是我的偶像)。这是 Web 安全史上第一个重量级的 XSS Worm,具有里程碑意义。
(2)2007年12月,百度空间收到蠕虫攻击,用户之间开始转发垃圾短消息。
(3) QQ 邮箱 m.exmail.qq.com 域名被发现反射型 XSS 漏洞
42011年新浪微博曾被黑客 XSS 攻击,黑客诱导用户点击一个带有诱惑性的链接,便会自动发送一条带有同样诱惑性链接微博。攻击范围层层扩大,也是一种蠕虫攻击。

XSS攻击有哪些类型?

反射型XSS攻击

顾名思义,恶意 JavaScript 脚本属于用户发送给网站请求中的一部分,随后网站又将这部分返回给用户,恶意脚本在页面中被执行。一般发生在前后端一体的应用中,服务端逻辑会改变最终的网页代码。
反射型 XSS 的攻击步骤:
(1)攻击者构造出特殊的 URL,其中包含恶意代码。
(2)用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
(3)用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
(4)恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

基于DOM的XSS攻击

目前更流行前后端分离的项目,反射型 XSS 无用武之地。 但这种攻击不需要经过服务器,我们知道,网页本身的 JavaScript 也是可以改变 HTML 的,黑客正是利用这一点来实现插入恶意脚本。
基于DOM 的 XSS 攻击步骤:
(1)攻击者构造出特殊的 URL,其中包含恶意代码。
(2)用户打开带有恶意代码的 URL。
(3)用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
(4)恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

存储型XSS攻击

又叫持久型 XSS,顾名思义,黑客将恶意 JavaScript 脚本长期保存在服务端数据库中,用户一旦访问相关页面数据,恶意脚本就会被执行。常见于搜索、微博、社区贴吧评论等。
存储型 XSS 的攻击步骤:
(1)攻击者将恶意代码提交到目标网站的数据库中。
(2)用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
(3)用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
(4)恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

各种XSS攻击的特点总结

通过上述各种XSS攻击类型,我们可以总结出他们具有以下几点区别

  • 反射型的 XSS 的恶意脚本存在 URL 里,存储型 XSS 的恶意代码存在数据库里。
  • 反射型 XSS 攻击常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
  • 存储型XSS攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
  • 而基于DOM的XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,其他两种 XSS 都属于服务端的安全漏洞。

XSS防范措施

由上面对XSS攻击的介绍我们知道,XSS攻击主要有两大步骤:
1)攻击者提交恶意代码
2)浏览器执行恶意代码
所以我们可以针对这两点来制定防范措施:

输入过滤

在用户提交时,由前端过滤输入,然后提交到后端,这种方法不可行,因为攻击者可能绕过前端过滤,直接构造请求,提交恶意代码。一般在写入数据库前,后端对输入数据进行过滤。虽然输入侧过滤能够在某些情况下解决特定的 XSS 问题,但会引入很大的不确定性和乱码问题。在防范 XSS 攻击时应避免此类方法。
预防存储型和反射型 XSS 攻击

  • 改成纯前端渲染,把代码和数据分隔开。
  • 对 HTML 做充分转义:对于用户的输入应该是永远不信任的,最普遍的做法就是转义输入输出的内容,对于括号,尖括号,斜杠进行转义
function escape(str) {  
    str = str.replace(/&/g, '&')  
    str = str.replace(/</g, '&lt;')  
    str = str.replace(/>/g, '&gt;')  
    str = str.replace(/"/g, '&quto;')  
    str = str.replace(/'/g, '&#39;')  
    str = str.replace(/`/g, '&#96;')  
    str = str.replace(/\//g, '&#x2F;')  
return str  
}  

预防 DOM 型 XSS 攻击

DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。在使用 .innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用.textContent、.setAttribute等。

如果用 Vue/React 技术栈,并且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 阶段避免 innerHTML、outerHTML 的 XSS 隐患。DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等,a标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。

页面劫持

原理

攻击者通过请求的数据传输过程进行数据修改,或者对网站域名进行泛域名解析以重定向网站,在网站中注入广告等

类型

跳转型劫持

通过泛域名解析(DNS解析)等将用户访问的页面打到其他网站,以进行恶意竞争,或者打到一些钓鱼网站进行用户个人利益和其他网站利益名誉侵害

注入型劫持

对于网站的请求资源进行拦截修改,加入恶意代码或者广告等

如何预防网络劫持

  • 最有效且暴力的直接换成HTTPS,建立安全通道
  • 进行漏洞监控,根据实际情况做出调整

点击劫持

什么是点击劫持?

点击劫持(Clickjacking)是一种通过视觉欺骗的手段来达到攻击目的手段,诱导用户触发点击。

点击劫持攻击原理?

攻击者将目标网站通过 iframe 嵌入到自己的网页中,通过 opacity 等手段设置 iframe 为透明的,使得肉眼不可见,这样一来当用户在攻击者的网站中操作的时候,比如点击某个按钮(这个按钮的顶层其实是 iframe),从而实现目标网站被点击劫持。

点击劫持防范措施?

  1. 在HTTP投中加入 X-FRAME-OPTIONS 属性,此属性控制页面是否可被嵌入 iframe 中,取值有以下三种:

(1) DENY:不能被所有网站嵌套或加载;

(2) SAMEORIGIN:只能被同域网站嵌套或加载;

(3) ALLOW-FROM URL:可以被指定网站嵌套或加载。

  1. 判断当前网页是否被 iframe 嵌套

Iframe

iframe在给我们的页面带来更多丰富的内容和能力的同时,也带来了不少的安全隐患。因为iframe中的内容是由第三方来提供的,默认情况下他们不受我们的控制,他们可以在iframe中运行JavaScirpt脚本、Flash插件、弹出对话框等等,这可能会破坏前端用户体验。

如何让自己的网站不被其他网站的iframe引用?

(1)js的防御方案:将下面这段代码放到网站页面的标签前,这样别人在通过iframe框架引用你的网站网页时,浏览器会自动跳转到你的网站所引用的页面上。

image.png

(2)使用X-Frame-Options防止网页被iframe:X-FRAME-OPTIONS是微软提出的一个http头,专门用来防御利用iframe嵌套的点击劫持攻击。其允许配置以下几个值
X-Frame-Options:DENY // 拒绝任何域加载
X-Frame-Options:SAMEORIGIN // 允许同源域下加载
X-Frame-Options:ALLOW-FROM // 可以定义允许frame加载的页面地址

如何禁止被使用的 iframe 对当前网站某些操作?

HTML5新增sandbox属性,用于提高iframe安全系数。iframe因安全问题而臭名昭著,这主要是因为iframe常被用于嵌入到第三方中,然后执行某些恶意操作。
Sandbox应用场景:现在我的网站需要使用 iframe 引用某网站,但是不想被该网站操作DOM、不想加载某些js(广告、弹框等)、当前窗口被强行跳转链接等,我们可以设置 sandbox 属性:

  • allow-same-origin:允许被视为同源,即可操作父级DOM或cookie等
  • allow-top-navigation:允许当前iframe的引用网页通过url跳转链接或加载
  • allow-forms:允许表单提交
  • allow-scripts:允许执行脚本文件
  • allow-popups:允许浏览器打开新窗口进行跳转
  • “”:设置为空时上面所有允许全部禁止

image.png

CDN劫持

CDN原理?

它的名字就叫做CDN——Content Delivery Network,内容分发网络。具体来说,CDN就是采用更多的缓存服务器(CDN边缘节点),布放在用户访问相对集中的地区或网络中。当用户访问网站时,利用全局负载技术,将用户的访问指向距离最近的缓存服务器上,由缓存服务器响应用户请求。(有点像电商的本地仓吧?)CDN应用广泛,支持多种行业、多种场景内容加速,例如:图片小文件、大文件下载、视音频点播、直播流媒体、全站加速、安全加速。

什么是CDN劫持?

网络上有很多黑客为了让用户能够登录自己开发的钓鱼网站,都会通过对CDN进行劫持的方法,让用户自动转入自己开发的网站。而很多用户却往往无法察觉到自己已经被劫持。其实验证被劫持的方法,就是输入任何网址看看所打开的网页是否和自己输入的网址一致,

CDN劫持防范措施

使用SRI来解决CDN劫持
SRI 全称 Subresource Integrity - 子资源完整性,是指浏览器通过验证资源的完整性(通常从 CDN 获取)来判断其是否被篡改的安全特性。
通过给 link 标签或者 script 标签增加 integrity 属性即可开启 SRI 功能,如下所示:

image.png

integrity 值分成两个部分,第一部分指定哈希值的生成算法(sha256、sha384 及 sha512),第二部分是经过 base64 编码的实际哈希值,两者之间通过一个短横(-)分割。integrity 值可以包含多个由空格分隔的哈希值,只要文件匹配其中任意一个哈希值,就可以通过校验并加载该资源。开启 SRI 能有效保证页面引用资源的完整性,避免恶意代码执行。
浏览器如何处理 SRI

  • 当浏览器在 script 或者 link 标签中遇到 integrity 属性之后,会在执行脚本或者应用样式表之前对比所加载文件的哈希值和期望的哈希值。
  • 当脚本或者样式表的哈希值和期望的不一致时,浏览器必须拒绝执行脚本或者应用样式表,并且必须返回一个网络错误说明获得脚本或样式表失败。

内容安全策略(CSP)

什么是CSP?

内容安全策略(Content Security Policy)简称 CSP,是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等.通过它可以明确的告诉客户端浏览器当前页面的哪些外部资源可以被加载执行,而哪些又是不可以的。

CSP的原理

CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。

CSP的意义

(1)CSP 的主要目标是减少和报告 XSS 攻击 ,XSS 攻击利用了浏览器对于从服务器所获取的内容的信任。恶意脚本在受害者的浏览器中得以运行,因为浏览器信任其内容来源,即使有的时候这些脚本并非来自于它本该来的地方。
(2)CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。作为一种终极防护形式,始终不允许执行脚本的站点可以选择全面禁止脚本执行

CSP的分类

  • Content-Security-Policy 配置好并启用后,不符合 CSP 的外部资源就会被阻止加载。
  • Content-Security-Policy-Report-Only 表示不执行限制选项,只是记录违反限制的行为。它必须与report-uri选项配合使用。

如何开启CSP?

(1)通过 HTTP 头配置 Content-Security-Policy,以下配置说明该页面只允许当前源和 apis.baison.com 这 2 个源的脚本加载和执行: image.png

(2)通过页面 标签配置,如下
image.png

常见用例(设置HTTP Header来举例)

  • 一个网站管理者想要所有内容均来自站点的同一个源 (不包括其子域名) 只允许加载本站资源
    Content-Security-Policy: default-src ‘self’
  • 一个网站管理者允许内容来自信任的域名及其子域名 (域名不必须与CSP设置所在的域名相同)
    Content-Security-Policy: default-src ‘self’ *.trusted.com
  • 一个网站管理者允许网页应用的用户在他们自己的内容中包含来自任何源的图片, 但是限制音频或视频需从信任的资源提供者(获得),所有脚本必须从特定主机服务器获取可信的代码.
    Content-Security-Policy: default-src ‘self’; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
  • 只允许加载HTTPS协议图片
    Content-Security-Policy: img-src https://*
  • 允许加载任何来源框架
    Content-Security-Policy: child-src ‘none’
    对于这种方式来说,这要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,而且CSP的兼容性不错.

HSTS

什么是HSTS?

HTTP严格传输安全(HSTS)是一种安全功能,web服务器通过它来告诉浏览器仅用HTTPS来与之通讯,而不是使用HTTP。
HSTS代表HTTP严格传输安全性,由IETF在2012年的RFC 6797中指定。创建它是为了在站点通过HTTPS运行时强制浏览器使用安全连接。
它是您添加到Web服务器的安全标头,并在响应标头中反映为Strict-Transport-Security。HSTS很重要,因为它解决了以下问题:

  • 访问者尝试使用您网站页面的不安全版本 (HTTP://) 的任何尝试都将自动转发到安全版本 (HTTPS://)。
  • 旧的HTTP书签和输入您网站的HTTP版本的人会让您面临中间人攻击。在这些攻击中,攻击者改变各方之间的通信并诱使他们认为他们仍在相互通信。
  • 不允许覆盖无效的证书消息,这反过来又保护了访问者。
  • Cookie劫持:当有人通过不安全的连接窃取会话cookie时,就会发生这种情况。Cookie可以包含各种有价值的信息,例如信用卡信息、姓名、地址等。
    注意,如果之前没有使用HTTPS协议访问过该站点,那么HSTS是不奏效的,只有浏览器曾经与服务器创建过一次安全连接并且网站通过HTTPS协议告诉浏览器它支持HSTS,那么之后浏览器才会强制使用HTTPS,即使链接被换成了HTTP。
    虽然我们的系统默认更喜欢HTTPS版本,但您也可以通过将您的HTTP站点重定向到您的HTTPS版本并在您的服务器上实施HSTS标头,使其他搜索引擎更清楚这一点。 —— 谷歌安全团队

如何配置HSTS?

在Apache中启用HSTS

将以下代码添加到您的虚拟主机文件中。

image.png

在NGINX中启用 HSTS

将以下代码添加到您的NGINX配置中。
image.png

事实上,添加HSTS标头有性能优势。如果有人试图通过HTTP访问您的站点,而不是发出HTTP请求,它只是重定向到HTTPS版本。