LoginSignup
127
99

More than 5 years have passed since last update.

Vueのv-htmlでXSSを回避する

Last updated at Posted at 2018-06-23

Vueのテンプレート構文の項を読めばわかることですが、v-htmlにはXSSの危険があることがわかります。

危険なコードの例を見てみましょう。

危険なコード
<template>
    <div id="app">
        <h1>サニタイズなし</h1>
        <p>{{ mastache }}</p>
        <p v-html="vhtml"></p>
    </div>
</template>

<script>
  export default {
    name: 'app',
    data() {
      return {
        mastache: 'mastache:<br><a onmouseover=alert(document.cookie)>click me!</a>',
        vhtml: 'vhtml:<br><a onmouseover=alert(document.cookie)>click me!</a>'
      }
    }
  }
</script>

このコードを実行すると、以下のような画面が描画され、click meにマウスオーバーしたときに攻撃コードが実行されてしまいます。
スクリーンショット 2018-06-23 21.57.22.png

v-htmlを利用して描画する項目に、ユーザからの入力が含まれる可能性がある場合は、v-htmlにサニタイズ処理を加えましょう。
以下の例では、sanitize-htmlを利用してVueの共通処理に仕込んで利用しています。

共通処理を設定
import Vue from 'vue'
import App from './App.vue'
import sanitizeHTML from 'sanitize-html'

Vue.prototype.$sanitize = sanitizeHTML
new Vue({
  el: '#app',
  render: h => h(App)
})
サニタイズを行う
<template>
    <div id="app">
        <h1>サニタイズなし</h1>
        <p>{{ mastache }}</p>
        <p v-html="vhtml"></p>
        <h1>サニタイズあり</h1>
        <p>{{ $sanitize(mastache) }}</p>
        <p v-html="$sanitize(vhtml)"></p>
    </div>
</template>

<script>
  export default {
    name: 'app',
    data() {
      return {
        mastache: 'mastache:<br><a onmouseover=alert(document.cookie)>click me!</a>',
        vhtml: 'vhtml:<br><a onmouseover=alert(document.cookie)>click me!</a>'
      }
    }
  }
</script>

これを実行すると、以下のようになります。
sanitize-htmlの初期設定では、aタグで許可される属性にonmouseoverは含まれていませんので、サニタイズされることがわかります。改行タグなどは、そのまま機能していますね。

vue-xss.mov.gif

サンプルコードは以下。
プロジェクトを作るのが面倒だったので、Springのサンプルプロジェクトの中に紛れています。

以上。

参考:
https://github.com/vuejs/vue/issues/6333
https://blog.sqreen.io/xss-in-vue-js/

127
99
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
127
99