處理v-html的潛在XSS風險


沒有進行防止xss攻擊的例子

<p v-html="test"></p>
 
export default {
  data () {
    return {
      test: `<a οnclick='alert("xss攻擊")'>鏈接</a>`
    }
}

結果,js事件被執行,彈出彈框,我們要杜絕這種情況,保留a標簽,攔截onclick事件

解決辦法

法一:

使用一個xss的npm包來過濾xss攻擊代碼,給指令的value包上一層xss函數

npm install xss --save
import xss from 'xss'

<p v-html="$xss(test)"></p>
 
import xss from 'xss'
export default {
  data () {
    return {
      test: `<a οnclick='alert("xss攻擊")'>鏈接</a>`
    }
}
 
Object.defineProperty(Vue.prototype, '$xss', {
  value: xss
})

法二:
在業務代碼里使用xss函數處理,不能保證團隊每一個成員都會使用xss函數處理,作為前端的架構師,我們需要從項目整體的考慮來處理這類問題,不能指望通過規范來約束團隊成員
1.引入xss包並掛載到vue原型上

mport xss from'xss'; Vue.prototype.xss = xss

2.在vue.config.js中覆寫html指令

chainWebpack: config => {
    config.module
        .rule("vue")
        .use("vue-loader")
        .loader("vue-loader")
        .tap(options => {
            options.compilerOptions.directives = {
                html(node, directiveMeta) {
                    (node.props || (node.props = [])).push({
                        name: "innerHTML",
                        value: `xss(_s(${directiveMeta.value}))`
                    });
                }
            };
            return options;
        });
}

在編譯前會將我們從vue-loader傳入的compilerOptions.directives和baseOptions.directives進行合並。 這樣我們就能覆蓋html指令。

沒有進行防止xss攻擊的例子

<p v-html="test"></p>
 
export default {
  data () {
    return {
      test: `<a οnclick='alert("xss攻擊")'>鏈接</a>`
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

結果,js事件被執行,彈出彈框,我們要杜絕這種情況,保留a標簽,攔截onclick事件

解決辦法

法一:

使用一個xss的npm包來過濾xss攻擊代碼,給指令的value包上一層xss函數

npm install xss --save
  • 1
import xss from 'xss'

<p v-html="$xss(test)"></p>
 
import xss from 'xss'
export default {
  data () {
    return {
      test: `<a οnclick='alert("xss攻擊")'>鏈接</a>`
    }
}
 
Object.defineProperty(Vue.prototype, '$xss', {
  value: xss
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

法二:
在業務代碼里使用xss函數處理,不能保證團隊每一個成員都會使用xss函數處理,作為前端的架構師,我們需要從項目整體的考慮來處理這類問題,不能指望通過規范來約束團隊成員
1.引入xss包並掛載到vue原型上

import xss from 'xss';
Vue.prototype.xss = xss
  • 1
  • 2

2.在vue.config.js中覆寫html指令

chainWebpack: config => {
    config.module
        .rule("vue")
        .use("vue-loader")
        .loader("vue-loader")
        .tap(options => {
            options.compilerOptions.directives = {
                html(node, directiveMeta) {
                    (node.props || (node.props = [])).push({
                        name: "innerHTML",
                        value: `xss(_s(${directiveMeta.value}))`
                    });
                }
            };
            return options;
        });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在編譯前會將我們從vue-loader傳入的compilerOptions.directives和baseOptions.directives進行合並。 這樣我們就能覆蓋html指令


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM