富文本编辑器的xss问题

前言:今天,客户要求加入富文本编辑器并且在非编辑模式下显示富文本的内容,在vue中需要用到v-html,但是突然联想到这样是很容易出现xss问题的,于是我们就要考虑如何防范

首先我们先要了解一下什么是XSS。XSS即跨网站指令码(Cross-site scripting,通常简称为:XSS)是一种网站应用的安全漏洞攻击,是代码注入的一种。它允许恶意使用者将代码注入到网页上,其他使用者在浏览网页时便会受到影响。这类攻击通常包含HTML以及JS等语言

XSS通常有三种形式:反射型,存储型,和DOM型

那么他是如何攻击的

xss通常是修改HTML节点或者执行js代码来攻击网站,例如通过URL来获取某些参数

<!-- http://www.chern.icu?name=<script>alert(1)</script> -->
<div>{{name}}</div>

上述案例中URL输入可能将HTML改为<div><script>alert(1)</script></div>

这样页面中就凭空多出了一段可运行脚本。这便是反射型攻击,也是DOM攻击

那么我们要如何进行防御

我们常见的做法便是对输出内容进行转义,对于引号,尖括号,斜杆等

function escape(str) {
	str = str.replace(/&/g, "&amp;");
	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
}

通过转义可以将攻击代码 <script>alert(1)</script> 变成

// -> &lt;script&gt;alert(1)&lt;&##x2F;script&gt;
escape('<script>alert(1)</script>')

对于显示富文本来说,不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式

var xss = require("xss");
var html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>');
// -> <h1>XSS Demo</h1>&lt;script&gt;alert("xss");&lt;/script&gt;
console.log(html);

以上示例使用了 js-xss来实现。可以看到在输出中保留了 h1 标签且过滤了 script 标签

最后拓展一下Cookie如何防范xss攻击

XSS(跨站脚本攻击)是指攻击者在返回的 HTML 中嵌入 javascript 脚本,为了减轻这些 攻击,需要在 HTTP 头部配上,set-cookie

httpOnly 这个属性可以防止 XSS,它会禁止 javascript 脚本来访问 cookie
secure- 这个属性告诉浏览器仅在请求为 https 的时候发送 cookie