背景:
最近公司saas系统做了个渗透测试,有一项是富文本安全相关的,需要在富文本字符串之前过滤掉一下恶意脚本之类的。这里用到了一个DOMPurify的库来过滤。
环境:node14.17 技术栈:vue3+ts
安装: npm:
npm install dompurify;
yarn:
yarn add dompurify;
引入
import DOMPurify from 'dompurify';
模拟XSS攻击(直接返回未过滤的html字符串):
const cleanHTML = computed(() => {
return article.value?.content + '<img src="http://www.123.com/114514.js" onerror=alert(1)>'
})
过滤前:
})
浏览器解析到img的src属性中的内容时,发起网络请求获取114514.js文件,但是文件并不存在,所以拿不到
img标签的src属性拿不到东西,触发onerror事件,出现弹窗
img标签渲染失败
审视元素发现有问题的img元素
加入过滤代码:
//这里的DOMPurify.sanitize已经可以过滤onerror之类的事件触发的恶意行为了,因为DOMPurify.sanitize本身就有默认的配置
const cleanHTML = computed(() => {
let str = article.value?.content + '<img src="http://www.123.com/114514.js" onerror=alert(1)>'
return DOMPurify.sanitize(str)
})
过滤通过img标签请求js文件
import DOMPurify from 'dompurify';
DOMPurify.addHook('uponSanitizeAttribute', function (node: any, attr: any) {
//检查src属性,如果 src 属性的值是一个 JavaScript 文件的 URL,那么就移除这个属性。
const regex = /^https?:\/\/.*\.js$/;//正则查询属性值是否为获取js文件的url
if (attr.attrName === 'src' && node.nodeName === 'IMG' && regex.test(attr.attrValue)) {
attr.attrName = ''
attr.attrValue = ''
attr.keepAttr = false;//是否保留这个属性
}
});
在addHook的方法中uponSanitizeAttribute事件他是没有返回值的(之前问过gpt说有返回值。。。,详细ctrl+左键点击查看index.d.ts文件)。所以这里直接修改attr对象的属性
过滤后:
弹窗和渲染失败的img都没了
浏览器也没获取114514.js文件
审视元素发现有问题的img标签无了