浅谈前端攻击

浅谈前端攻击

三月 25, 2021

刷题时,遇到前端攻击的问题。这个也是看了一百遍忘一百遍。所以写一遍,巩固记忆。

XSS攻击

先来个简单的白话描述什么是XSS攻击

Cross-Site Scripting(跨站脚本攻击)简称 XSS

是没有过滤用户输入,而直接把用户输入插入到html中,执行不可靠代码造成损失的攻击。

如。用户在个input中输入

<script>alert('xss')</script>

如果反显时直接将上面的的用户输入innerHTML = [userinput]。那么就会在页面里插入一段js。

如果用户插入的是一段自己的远程js。那么这段远程js是可以访问当前的任何数据,包括登陆信息,这样攻击者就的js就能访问被攻击者的账户信息了。

这样就产生了一次XSS攻击。

根据分类,可以分三种类型的XSS攻击:存储型反射型DOM型

存储型一般发生在有评论的网站。攻击者提交评论时带有攻击性的内容。在展示评论时。如果没有特殊处理,可能会被注入代码。

反射型是攻击代码放在url中,如果没有处理,url中的代码以某种形式注入到页面中,就会被攻击。

前两者指的都是后端的锅,指的是,后端直接拼接html返回给前端造成的问题。如PHP的模板语法等。

DOM型指的是浏览器端不加处理插入未经处理的输入,造成的注入。

详细的看链接:前端安全系列(一):如何防止XSS攻击? - 美团技术团队

如何防范

html转义

正常情况下,需要对不可靠信息进行过滤,比如对

<script>alert('xss')</script>

转成

&quot;&gt;&lt;script&gt;alert(&#x27;XSS&#x27;);&lt;&#x2F;script&gt

而实际上。转义不只是转<,>等符号,实际情况要更复杂。应该用非常成熟的转义库操作才行。具体原因见链接。

在页面中展示是一样的

禁止危险输入

尽量不要使用 v-html/dangerouslySetInnerHTML。React-dom的render会自动转义,不用特殊的方法就很安全。

尽量使用document.createElementsetAttribute等方法操作dom,不要拼接字符串然后的方法。

避免用能执行字符串代码的方法

慎用用evalsetTimeoutsetIntervalinnerHTMLouterHTMLdocument.write这些方法不能执行不可靠的内容。

(亲测,最新chrome已经无法用innerHTMLdocument.write插入字符串script标签,会报Uncaught SyntaxError: Invalid or unexpected token错误)

CSP

html头部添加CSP限制,完全禁止外域js代码加载

前后端分离

如上所说,目前新版浏览器已经禁止直接插入危险字符串(如<script>),所以前端操作dom会相对安全许多。以前的后端是直接拼接html返回给浏览器的形式,浏览器是无法识别是不是安全代码。所以危险性会高不少。所以从某种角度说,避免后端拼接html,采用前后端分离,也是防范XSS的一种方法。

日常开发

日常开发其实不太可能会遇到xss攻击

  1. React-dom会自动转义。只要不用innerHTML、outerHTML、document.write、eval、v-html/dangerouslySetInnerHTML插入不可靠数据即可
  2. 对简单的项目,加上CSP禁止外域js加载
  3. 禁止后端拼接html返回前端

CSRF

CSRF全称为跨站请求伪造(Cross-site request forgery)

一次经典攻击流程就是

  1. 小明在a网站登陆
  2. 小黑给小明推了个链接,小白点击链接
  3. 链接里包含了个自动提交的form表单,表单的提交内容即a网站的某个很有价值的链接(如转账等)此时的提交会带上小明在a网站上登陆的cookie
  4. 这样小明就在不知情的情况下做了对自己不利的操作。

详细的看链接:前端安全系列(二):如何防止CSRF攻击

如何防范

加上随机token

目前公司就是这么做的。原理是。在页面加载的时候,随机生成一个token传给前端,且存入session。

然后前端在每个ajax中写入该token。后端拿到该token,与session里的比对。如果匹配得上,则能证明是自己的页面发起的token。一般CSRF攻击没法访问自己页面的js环境,无法拿到token。

随机token也有自己的局限。

  1. 需要手动在每个ajax请求添加token
  2. 如果是大型分布式网站,存储token将会带来同步的问题。
  3. 需要消耗计算性能

校验referer

每个浏览器发起请求时,都会自动在http请求头写入参数,该参数固定是发起请求页面的协议 + 域名。后端可以判断referer是不是自己的域名,从而判断是否是自己的页面。

双从cookie

这个原理同随机token,只是不需要生成token,而是在ajax请求体中带上cookie。后端通过比对请求体中的cookie和请求头里的cookie,从而判断是不是自己的网站。因为第三方攻击网站无法访问自己网站的js环境,无法读取cookie。相对随机token好处在于省去把token存储在session造成同步session的问题和计算token产生额外消耗的问题

双重cookie的缺点在于

  1. cookie一般量大,造成get请求不美观。
  2. http请求体量大,占用带宽

新浏览器新出的特性,可以让cookie只从本域名发出。

语法是

Set-Cookie: CookieName=CookieValue; SameSite=XXX;

SameSite有三个值 分别是

  • Strict
  • Lax
  • None

Strict

完全禁止第三方cookie。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。

Lax

规则是: 大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

请求类型 示例 正常情况 Lax
链接 <a href=”” /> 发送Cookie 发送Cookie
预加载 <link ref=”preload” href=” /> 发送Cookie 发送Cookie
GET表单 <form method=”GET” /> 发送Cookie 发送Cookie
POST表单 <form method=”POST” /> 发送Cookie 不发送
iframe <iframe src=”” /> 发送Cookie 不发送
ajax 发送Cookie 不发送
Image <img src=”” /> 发送Cookie 不发送

基本上杜绝了CSRF攻击,注意不要用get接口写重要的逻辑就好。。

None

关闭samesite,注意必须跟着Secure使用。

Set-Cookie: widget_session=abc123; SameSite=None; Secure