• 前端安全实用防御方案


     

    XSS防御

    1. 转义字符(正则替换)

      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. 转义字符(js-xss插件)

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

      1. 设置 HTTP Header 中的 Content-Security-Policy

        1. 只允许加载本站资源

          Content-Security-Policy: default-src ‘self’
        2. 只允许加载 HTTPS 协议图片

          Content-Security-Policy: img-src https://*
        3. 允许加载任何来源框架

          Content-Security-Policy: child-src 'none'
      2. 设置 meta 标签的方式 <meta http-equiv="Content-Security-Policy">

    CSRF防御

    1. SameSite:可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送,可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。

    2. 验证Referer:对于需要防范 CSRF 的请求,我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的。

    3. Token:服务器下发一个随机 Token,每次发起请求时将 Token 携带上,服务器验证 Token 是否有效。

    点击劫持防御

    1. X-FRAME-OPTIONS:X-FRAME-OPTIONS 是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防御用 iframe 嵌套的点击劫持攻击(该响应头有三个值可选,分别是:DENY,表示页面不允许通过 iframe 的方式展示;SAMEORIGIN,表示页面可以在相同域名下通过 iframe 的方式展示;ALLOW-FROM,表示页面可以在指定来源的 iframe 中展示)。

    2. JS 防御

      <head>  <style id="click-jack">    html {      display: none !important;    }</style></head><body>  <script>    if (self == top) {      var style = document.getElementById('click-jack')      document.body.removeChild(style)    } else {      top.location = self.location    }</script></body>

    运营商劫持防御

    1. 思路:在运营商插入非法代码之前监听dom变动

    2. step1:挂载dom监听器

    3. step2:处理dom变动,进行白名单筛选

    4. step3:处理运营商非法注入

    5. 代码实现:

      class HijackPreventor {    constructor(watchNode = Array.from(document.getElementsByTagName('body'))[0],report=()=>{}) {        this.whiteList = []        this.whiteRegList = []        this.filterTagList = ['script']        this.report = report        this.setObserver(watchNode)    }
      /** * 设置域名白名单 * @param {Array|String} list */ setWhilteList(item) { if (item instanceof Array) { this.whiteList = item } else if (typeof item === 'string') { this.whiteList.push(item) } else { console.error('[HijackPreventor]: Please set an Array or String type parameter to "setWhilteList" ') return; } this.whiteRegList = this.whiteList.map(wl => new RegExp('/.+?//' + wl + '|//' + wl + '|.+?.' + wl + '|^' + wl) ) }
      /** * 挂载dom监听器 * @param {Node} node */ setObserver(watchNode) { const observer = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; const isSupportObserver = !!observer if (isSupportObserver) { console.info('[HijackPreventor]: The preventor is running...') new observer((records) => { this.filterSafeScript(records) }).observe(watchNode, { childList: true, attributes: true }) } else { console.error('[HijackPreventor]: Your platform is not supported with "window.MutationObserver",please update.') } }
      /** * 获取非法注入 * @param {Node} records */ filterSafeScript(records) { const { filterTagList, whiteRegList } = this let badInjections = [] records.forEach(record => { const addedNodes = Array.from(record.addedNodes) addedNodes.forEach((node) => { if (node.tagName && ~filterTagList.indexOf(node.tagName.toLowerCase())) { const isInWhiteList = whiteRegList.some((reg) => reg.test(node.src)) if (!isInWhiteList) { badInjections.push({ badNode: node, badSource: node.src }) } } }) }) this.handleBadInjections(badInjections) }
      /** * 处理非法注入 * @param {Array} badInjections */ handleBadInjections(badInjections) { badInjections.forEach(({ badNode, badSource }) => { badNode.remove(); // 移除非法注入节点 console.warn(`[HijackPreventor]: The source "${badSource}" is invalid,removed it already.`) }) this.report(badInjections) }
      /** * 模拟插入script,用来测试 * @param {Node} appendNode */ mockHijack(appendNode = document.getElementsByTagName('body')[0]) { const node = document.createElement("script"); node.src = 'https://cdn.bootcss.com/zepto/1.0rc1/zepto.min.js' appendNode.appendChild(node) }}
  • 相关阅读:
    CYQ.Data 轻量数据层之路 V4.0 版本发布
    基于MSAA的自动化封装和设计—python版(转)
    【自然框架】之鼠标点功能现(二):表单控件的“应用”—— 代码?只写需要的!
    论管理员的不作为!!!
    【自然框架】之通用权限的Demo(二):添加人员、添加账户、添加角色里面的账户以及列表的权限验证
    使用接口来统一控件的取值、赋值和初始化
    【自然框架】之通用权限(八):权限到字段(列表、表单、查询)
    辩论赛 VS 讨论组
    【自然框架】表单控件 之 一个表单修改多个表里的记录
    【自然框架】之“解耦”初探
  • 原文地址:https://www.cnblogs.com/liuhao-web/p/13184597.html
Copyright © 2020-2023  润新知