在vue项目中我们经常会使用v-bind指令绑定对应的方法或属性,让组件或DOM元素能够解析或读取动态数据,从而实现我们需要的功能,但是如果绑定直接使用了用户输入信息,很可能会引起xss攻击,从而导致普通用户遭受莫名损失,下面我们列举一下常见的xss攻击方式
1. 排查 v-html、innerHTML、outerHTML、document.write的使用,判断是否有用户挟持的可能
示例:
<template>
<div :innerHTML="attackUrl"></div>
</template>
<script setup>
import {ref} from "vue";
const attackUrl = ref('<img src="" onerror="alert(`xss`)">')
</script>
<style lang="less" scoped>
</style>
运行结果:
2. 排查onclick、onerror、onload、onmouseover、href的使用,判断是否有用户挟持的可能,一般情况以上方法均属于内部方法,不应被外部用户所挟持和干扰
示例:
<template>
<a :href="attack">abc</a>
</template>
<script setup>
const attack = 'javascript: alert("href xss")'
</script>
<style lang="less" scoped>
</style>
运行结果:
3. 排查eval()、setTimeout()、setInterval()能把字符串作为代码运行的使用,判断是否有使用的必要以及挟持的可能性,正常来说eval是当前项目编码中严禁使用的方法
<template>
<div>setTimeout</div>
</template>
<script setup>
const outsideAttack = 'alert("outside xss")'
setTimeout(outsideAttack, 100)
</script>
<style lang="less" scoped>
</style>
运行结果:
4、针对使用了很广泛的elemmentUI组件库,排查$comfirm、$alert、$prompt是否有用户挟持的可能,尽量避免外部输入的直接交互
<template>
<div>$alert</div>
</template>
<script setup>
import { ElMessage, ElMessageBox } from 'element-plus'
ElMessageBox.alert('<a href="javascript: alert(`xss`)"><strong>这是 <i>HTML</i> 片段 </strong></a>', 'HTML 片段', {
dangerouslyUseHTMLString: true
});
</script>
<style lang="less" scoped>
</style>
运行结果:
推荐解决方案:
- 针对v-html,可以使用第三方库
dompurify进行转义输出
<template>
<div v-html="safeHtml"></div>
</template>
<script setup>
import {ref} from "vue";
import DOMPurify from 'dompurify';
const dirtyHtml = ref(`<a href="javascript: alert('xss')">这是安全的文本</a>`);
const safeHtml = ref('');
// 使用DOMPurify清洗HTML
safeHtml.value = DOMPurify.sanitize(dirtyHtml.value);
</script>
- HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie
- 合理设置Content Security Policy,禁止外域代码加载