在上文中,咱们已经熟悉了 XSS 攻击的定义、分类以及防御手段了,咱们知道 XSS 防御最重要和有效的手段就是进行 XSS-Filter 处理。既然 XSS-Filter 如此重要,那咱们怎么开发一个 XSS-Filter 库呢?这篇文章会告诉你答案,如今就跟随我,一步步开发一个 XSS-Filter 吧?javascript
其实对于一个 XSS-Filter 来讲,无非就是作字符串替换的操做,即:java
replace(/a/, /b/);
复制代码
也就是说,咱们要作的就是将一些字符串替换成另一些字符串。这样咱们能够找到那些可能引起安全问题的标签或者属性替换成(转义成)安全的字符,或者将除了某些安全标签或属性以外的其余字符都进行转义或过滤。这样一来就对应两种思路,即:git
在计算机安全中,黑名单只是一种防止已知恶意程序运行的简单有效的方法,更新黑名单能够快速经过更新服务器来实现,大多数防病毒程序使用的是黑名单技术来阻止已知威胁,垃圾邮件过滤器每每须要依赖于黑名单技术。 黑名单技术只在某些应用中可以发挥良好做用,固然前提是黑名单内容准确性和完整性。 黑名单最重要的问题就是,它只能抵御已知的有害的程序和发送者,不可以抵御新威胁(零日攻击等),对进入网络的流量进行扫描并将其与黑名单对比还可能浪费至关多的资源以及下降网络流量。github
白名单技术的宗旨是不阻止某些特定的事物,它采起了与黑名单相反的作法,利用一份“已知为良好”的实体(程序、电子邮件地址、域名、网址)名单,如下是白名单技术的优势:安全
白名单技术的优势是,除了名单上的实体外都不能运行或者经过,缺点则是,不在名单上的实体都不能运行和经过。可见,优势也是缺点。服务器
咱们已经了解了黑名单和白名单两种技术了。在实现 XSS-Filter 时,对比了黑名单和白名单的特色,咱们应该选择白名单来实现,缘由以下:网络
/* * { * key: value * } * key 标签名 value 支持的属性列表 */
var whiteList = {
a: ['target', 'href', 'title'],
abbr: ['title'],
address: [],
area: ['shape', 'coords', 'href', 'alt'],
article: [],
aside: [],
audio: ['autoplay', 'controls', 'loop', 'preload', 'src'],
b: [],
bdi: ['dir'],
bdo: ['dir'],
big: [],
blockquote: ['cite'],
br: [],
caption: [],
center: [],
cite: [],
code: [],
col: ['align', 'valign', 'span', 'width'],
colgroup: ['align', 'valign', 'span', 'width'],
dd: [],
del: ['datetime'],
details: ['open'],
div: [],
dl: [],
dt: [],
em: [],
font: ['color', 'size', 'face'],
footer: [],
h1: [],
h2: [],
h3: [],
h4: [],
h5: [],
h6: [],
header: [],
hr: [],
i: [],
img: ['src', 'alt', 'title', 'width', 'height'],
ins: ['datetime'],
li: [],
mark: [],
nav: [],
ol: [],
p: [],
pre: [],
s: [],
section: [],
small: [],
span: [],
sub: [],
sup: [],
strong: [],
table: ['width', 'border', 'align', 'valign'],
tbody: ['align', 'valign'],
td: ['width', 'rowspan', 'colspan', 'align', 'valign'],
tfoot: ['align', 'valign'],
th: ['width', 'rowspan', 'colspan', 'align', 'valign'],
thead: ['align', 'valign'],
tr: ['rowspan', 'align', 'valign'],
tt: [],
u: [],
ul: [],
video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width']
};
复制代码
咱们首先将输入的 HTML Dom String 转化为 HTML 标签以及 HTML 属性,而后再经过白名单将 HTML 标签和属性转换。 好比咱们能够这么作:dom
// 输入HTML Dom String
var domString = '<div><a></a><script></script></div>';
// 找到第一个标签 div, 在白名单里,不作转义操做
...
// 找到第*个标签 script,不在白名单里,作转义操做
<script> ===> <script>
复制代码
对属性的处理也相似,咱们尤为注意对 src 和 href 属性的处理。xss
function safeAttrValue(name, value) {
var Reg = /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi;
if (name === "href" || name === "src") {
value = value.trim();
if (value === "#") return "#";
if (
!(
value.substr(0, 7) === "http://" ||
value.substr(0, 8) === "https://" ||
value.substr(0, 7) === "mailto:" ||
value.substr(0, 4) === "tel:" ||
value[0] === "#" ||
value[0] === "/"
)
) {
// 若是href和src属性不是连接则清空,防止href="javascript:alert(/xss/)"这种情形
return "";
}
} else if (name === "background") {
if (reg.test(value)) {
// 若是包含javascript脚本则清空
return "";
}
}
// escape `<>"` before returns
var REGEXP_QUOTE = /"/g;
var REGEXP_LT = /</g;
var REGEXP_GT = />/g;
value =value.replace(, """).replace(REGEXP_LT, "<").replace(REGEXP_GT, ">");
return value;
}
复制代码
总体的流程以下图所示: ide
固然,实现一个XSS-Filter要考虑的东西远远要多不少,这里主要是给你们提供一个思路,具体的源码你们能够参见网上一个比较流行的XSS库的实现,仓库,这里的源码都是用es5语法写的,总体看起来比较凌乱,你们有兴趣能够用最新的ES6语法写个相似的仓库。
又到告终尾了,很开心你们能坚持看到最后。XSS防护仍是很值得你们去深刻研究的,总之一句话,但愿咱们你们能从个人文章学到知识。最后,祝你们工做愉快!
@Author: WaterMan