美文网首页
【前端】安全防御篇

【前端】安全防御篇

作者: irenb | 来源:发表于2020-09-06 21:11 被阅读0次

    XSS防御

    1. 转义字符(正则替换)
    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
    }
    
    1. 转义字符(js-xss插件)
    const xss = require('xss')
    let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
    
    1. CSP
      1》设置 HTTP Header 中的 Content-Security-Policy
    • 只允许加载本站资源
    Content-Security-Policy: default-src ‘self’
    
    • 只允许加载 HTTPS 协议图片
    Content-Security-Policy: img-src https://*
    
    • 允许加载任何来源框架
    Content-Security-Policy: child-src 'none'
    

    2》设置 meta 标签的方式

    CSRF防御

    • SameSite:可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送,可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。
    • 验证Referer:对于需要防范 CSRF 的请求,我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的。
    • 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)
        }
    }
    

    相关文章

      网友评论

          本文标题:【前端】安全防御篇

          本文链接:https://www.haomeiwen.com/subject/mfkhektx.html