常见的前端安全CSRF/XSS以及常规安全策略

1、CSRF:跨站请求伪造(Cross-site request forgery);

原理:

(1)用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

(2)在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

(3)用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

(4)网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

(5)浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。 

侧重点:

不注入恶意脚本,侧重于伪造请求,借刀杀人,在用户不知情的情况下,借用户的名义干坏事。

防御:

(1)严格的跨域请求限制:验证 HTTP Referer 字段,判断页面来源(判断是不是来源于自己的网站)

(2)为cookie设置SameSite=Strict 表示禁止跨域请求;

(3)关键接口使用短信验证码等双重验证;

(4)在请求地址中添加 token 并验证;

(5)在 HTTP 头中自定义属性并验证

2、XSS:跨站脚本攻击(Cross-site scripting);

原理:向页面注入脚本(如:评论区/输入框、富文本等区域)

侧重点:脚本,千方百计的注入并执行恶意脚本;

攻击危害:

注入方式:

一切用户可以输入的地方,都是XSS攻击的用武之地。所以对于前端来说,一切用户的输入都是不安全的。主要通过URL参数注入输入框注入

分类:

反射型和DOM型都要是通过参数的方式注入:

也就是说,黑客会引诱用户点击黑客精心准备的带有恶意代码的链接

 

 

防御:(对用户的输入和输出做严格的把控)

对输入进行过滤(输入格式校验、过滤特殊标签和事件属性、限制输入程度),尽量不要用v-html指令,对输出进行转义。

 3、点击劫持攻击

原理:

黑客在自己的网站,使用隐藏的<iframe>嵌入其他网页,诱导用户按顺序点击

预防:

使用JS预防:

判断当前域名与子域名是否相同,不同则提醒不安全页面

增加请求头属性限制:只能加载同域名网页

4、 Vue项目防范XSS攻击问题

在 Vue 项目中,XSS攻击是一个常见的安全问题。

① 什么是XSS攻击

XSS(Cross-Site Scripting)攻击是一种常见的Web安全漏洞,攻击者通过在 Web 页面中注入恶意脚本,从而在用户浏览器中执行恶意代码,窃取用户的敏感信息或者进行其他恶意行为。

这种攻击行为的本质,是在一个网站上的恶意攻击者将一些非法的脚本或者标签插入某个网页,使访问者在浏览的时候,这些非法脚本或者标签被执行,在用户的浏览器中发起恶意操作,如窃取 cookies、对网站发起 CSRF 攻击等。

② 如何防范XSS攻击

1)对用户输入进行过滤和验证

在接收用户输入时,我们应该对用户输入进行过滤和验证,确保用户输入的内容符合我们的预期。例如,我们可以使用正则表达式过滤掉高危标签和 JavaScript 代码,或者使用第三方库对用户输入进行过滤。

转义字符:

function escape(str) {
    str = str.replace(/&/g, '&amp;')
    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
}

2)使用CSP(Content Security Policy)

CSP是一种Web安全策略,可以限制Web页面中可以加载的资源,从而防止XSS攻击。我们可以在Web页面的HTTP头中添加CSP策略,限制Web页面中可以加载的资源类型和来源。

CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。

通常可以通过两种方式来开启 CSP:

  • 设置 HTTP Header 中的 Content-Security-Policy
  • 在入口文件的 head 添加 meta 标签

这里以设置 HTTP Header 来举例:

<meta http-equiv="Content-Security-Policy" content="script-src "self";style-src "self"">

 以下指令说明:允许自身css、js和高德地图api、地图数据。 

<meta 
    http-equiv="Content-Security-Policy" 
    content="style-src "self" "unsafe-inline";script-src "self" "unsafe-inline" "unsafe-eval" https://webapi.amap.com https://restapi.amap.com https://vdata.amap.com https://appx/web-view.min.js;worker-src blob:">

script-src:只加载当前域名服务器下的资源,且允许 eval 执行脚本。因为 webpack 在development 模式下大量使用 eval 进行脚本注入,且在 development 中常用的 souce-map是cheap-module-eval-source-map。

如果 script-src 设置成 ‘self’ 会阻止 eval 的使用。

style-src:只加载当前域名服务器下的资源,且允许使用内联资源。有时候无论在开发环境还是生产环境,可能都是通过webpack打包把CSS内容打包到JS文件里面。加载页面时,JS脚本会在页面中插入一个个style标签补充层叠样式模型。如果style-src设置成‘self’会阻止style内联样式的插入和执行。

Content-Security-Policy - HTTP | MDN

  • 只允许加载本站资源 

Content-Security-Policy: default-src 'self'

  • 只允许加载 HTTPS 协议图片

Content-Security-Policy: img-src https://*

  • 允许加载任何来源框架

Content-Security-Policy: child-src 'none'

对于这种方式来说,只要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,并且 CSP 的兼容性也不错。

3)X-XSS-Protection

此 header 能在用户浏览器中开启基本的 XSS 防御。它不能避免一切 XSS 攻击,但它可以防范基本的 XSS。

例如,如果浏览器检测到查询字符串中包含类似 ​<script>​ 标签之类的内容,则会阻止这种疑似 XSS 攻击代码的执行。这个 header 可以设置三种不同的值:​0​、​1​ 和 ​1; mode=block​。

4)白名单

但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。

const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')

console.log(html) // <h1>XSS Demo</h1>&lt;script&gt;alert("xss");&lt;/script&gt;

以上示例使用了 js-xss 来实现,可以看到在输出中保留了 h1 标签且过滤了 script 标签。

5)HttpOnly Cookie

HttpOnly 是一个设置 cookie 是否可以被 javasript 脚本读取的属性,浏览器将禁止页面的 Javascript 访问带有 HttpOnly 属性的 Cookie。

这是预防 XSS 攻击窃取用户 cookie 最有效的防御手段。Web应用程序在设置cookie时,将其属性设为 HttpOnly,就可以避免该网页的cookie被客户端恶意 JavaScript 窃取,保护用户cookie信息。

const express = require('express');
const app = express();
app.use(function(req, res, next) {
    res.setHeader('Content-Type', 'text/html;charset=utf-8');
    // 模拟设置用户cookie
    // 可以把类似敏感信息都设置 httpOnly: true
    res.cookie('token', 'onlyHttpUse', { httpOnly: true });
    next();
});

6) IP访问限制

系统后台增加 ip 访问限制,主要是针对获取 cookie 伪造管理员登入方式;

7)白名单无法解决的,禁止掉触发事件;

8)验证码:防止脚本冒充用户提交危险操作;

9)输入内容长度控制:对于不受信任的输入,都应该限定一个合理的长度。虽然无法完全防止 XSS 发生,但可以增加 XSS 攻击的难度。

10)Javacript过滤

③ 如何使用 Vue.js 防范 XSS 攻击

1)使用 v-text 指令

可以将数据作为纯文本插入到DOM中,而不是作为HTML代码插入到DOM中。这样可以防止恶意脚本被执行。

<template>
  <div v-text="message"></div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, <script>alert("XSS")</script> World!'
    };
  }
};
</script>

在上面的代码中,我们使用 v-text 指令将message作为纯文本插入到DOM中,而不是作为HTML代码插入到DOM中。这样可以防止恶意脚本被执行。

2)使用 Vue.js 的过滤器

可以对数据进行格式化和转换,从而防止恶意脚本被执行。

<template>
  <div>{{ message | escape }}</div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, <script>alert("XSS")</script> World!'
    };
  },
  filters: {
    escape(value) {
      // 对value进行过滤和转换
      return value.replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }
  }
};
</script>

在上面的代码中,我们使用 Vue.js 的过滤器 escape 对 message 进行过滤和转换,将所有的<和>替换为&lt;和&lg;,从而防止恶意脚本被执行。

3)可以使用 lodash 里面的 escape 方法对客户信息进行转译

import _escape from "lodash/escape"
Vue.prototype.$escape = _escape

<div v-html="`<span>${$escape(message)}</span>`"></div>

4) 使用xss工具

npm i xss -S

1)在页面中引入资源且生成XSS过滤器,对内容进行过滤 :

var xss = require("xss") 
const option={} // 自定义设置
const myxss = new xss.FilterXSS(option);
const line="<script type="text/javascript">alert(1);</script>"
var html = myxss.process(line);
console.log(html); 
// &lt;script type="text/javascript"&gt;alert(1);&lt;/script&gt;

2)如果我想不过滤 img 标签的 onerror 属性,或者不过滤 style 标签。

通过设置whiteList可选择性的保留特定标签及其属性

const option = {
    whiteList: {
        img: ["src","onerror"] // img标签保留src,onerror属性
        style: ["type"] // style标签默认是不在whileList属性里的,现在添加上去
    }
}
const myxss = new xss.FilterXSS(option);

letline="<img src="./123.png" onerror="alert(1);" alt="123">"
let html = myxss.process(line);
console.log(html); // <img src="./123.png" onerror="alert(1);">

line="<style type="text/css">color:white;</style>"
html = myxss.process(line);
console.log(html); // <style type="text/css">color:white;</style>

xss默认的whiteList可以通过console.log(xss.whiteList)显示。 

3)如果想彻底过滤掉类似script/noscript标签,option可如下设置:

const option = {
    stripIgnoreTagBody: ["script", "noscript"],
}
const myxss = new xss.FilterXSS(option)

let line = "<script type="text/javascript">alert(1);</script>"
let html = myxss.process(line)
console.log(html.length) // 输出0,即html被转化为空字符串

line = "<noscript>123</noscript>"
html = myxss.process(line)
console.log(html.length) // 输出0,即html被转化为空字符串

stripIgnoreTagBody用于设置不在 whiteList 的标签的过滤方法。

例如 script,不在 whiteList 会被执行xss内部的 escapeHtml 方法。如一开头的例子会把“<”,“>”进行转义。

但如果stripIgnoreTagBody中添加了script。则会直接把整个script标签过滤掉。

4)xss默认生成的过滤器是会过滤掉任何标签的class属性。

如果我们不想过滤任何在whiteList的标签的class属性,可以这么设置:

const option = {
    onIgnoreTagAttr: function(tag, name, value, isWhiteAttr) {
        if (["style", "class"].includes(name)) {
            return `${name} = "${xss.escapeAttrValue(value)}"`
        }
    },
}
const myxss = new xss.FilterXSS(option);
let line="<div class="box"></div>"
let html = myxss.process(line);
console.log(html); // <div class="box"></div>

onIgnoreAttr 方法用于设置白名单中特定属性的过滤方法。

5、前端的常规安全策略

① 定期请第三方机构做安全性测试和漏洞扫描

② code review 保证代码质量

③ 默认项目中设置对应的 Header 请求头,如 X-XSS-Protection、 X-Content-Type-Options 、X-Frame-Options Header、Content-Security-Policy 等等

④ 尽量不用v-html、在有输入框的地方要对输入做拦截和校验等

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值