XSS CODE
跨站脚本攻击
This commit is contained in:
339
test/test_custom_method.js
Normal file
339
test/test_custom_method.js
Normal file
@@ -0,0 +1,339 @@
|
||||
/**
|
||||
* 测试XSS 自定义处理函数
|
||||
*
|
||||
* @author 老雷<leizongmin@gmail.com>
|
||||
*/
|
||||
|
||||
var assert = require('assert');
|
||||
var xss = require('../');
|
||||
var debug = require('debug')('xss:test');
|
||||
|
||||
|
||||
describe('test custom XSS method', function () {
|
||||
|
||||
it('#onTag - match tag', function () {
|
||||
var source = 'dd<a href="#"><b><c>haha</c></b></a><br>ff';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onTag: function (tag, html, options) {
|
||||
debug(arguments);
|
||||
i++;
|
||||
if (i === 1) {
|
||||
assert.equal(tag, 'a');
|
||||
assert.equal(html, '<a href="#">');
|
||||
assert.equal(options.isClosing, false);
|
||||
assert.equal(options.position, 2);
|
||||
assert.equal(options.sourcePosition, 2);
|
||||
assert.equal(options.isWhite, true);
|
||||
} else if (i === 2) {
|
||||
assert.equal(tag, 'b');
|
||||
assert.equal(html, '<b>');
|
||||
assert.equal(options.isClosing, false);
|
||||
assert.equal(options.position, 14);
|
||||
assert.equal(options.sourcePosition, 14);
|
||||
assert.equal(options.isWhite, true);
|
||||
} else if (i === 3) {
|
||||
assert.equal(tag, 'c');
|
||||
assert.equal(html, '<c>');
|
||||
assert.equal(options.isClosing, false);
|
||||
assert.equal(options.position, 17);
|
||||
assert.equal(options.sourcePosition, 17);
|
||||
assert.equal(options.isWhite, false);
|
||||
} else if (i === 4) {
|
||||
assert.equal(tag, 'c');
|
||||
assert.equal(html, '</c>');
|
||||
assert.equal(options.isClosing, true);
|
||||
assert.equal(options.position, 30);
|
||||
assert.equal(options.sourcePosition, 24);
|
||||
assert.equal(options.isWhite, false);
|
||||
} else if (i === 5) {
|
||||
assert.equal(tag, 'b');
|
||||
assert.equal(html, '</b>');
|
||||
assert.equal(options.isClosing, true);
|
||||
assert.equal(options.position, 40);
|
||||
assert.equal(options.sourcePosition, 28);
|
||||
assert.equal(options.isWhite, true);
|
||||
} else if (i === 6) {
|
||||
assert.equal(tag, 'a');
|
||||
assert.equal(html, '</a>');
|
||||
assert.equal(options.isClosing, true);
|
||||
assert.equal(options.position, 44);
|
||||
assert.equal(options.sourcePosition, 32);
|
||||
assert.equal(options.isWhite, true);
|
||||
} else if (i === 7) {
|
||||
assert.equal(tag, 'br');
|
||||
assert.equal(html, '<br>');
|
||||
assert.equal(options.isClosing, false);
|
||||
assert.equal(options.position, 48);
|
||||
assert.equal(options.sourcePosition, 36);
|
||||
assert.equal(options.isWhite, true);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, 'dd<a href="#"><b><c>haha</c></b></a><br>ff');
|
||||
|
||||
});
|
||||
|
||||
it('#onTag - return new html', function () {
|
||||
var source = 'dd<a href="#"><b><c>haha</c></b></a><br>ff';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onTag: function (tag, html, options) {
|
||||
debug(html);
|
||||
return html;
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, source);
|
||||
});
|
||||
|
||||
it('#onIgnoreTag - match tag', function () {
|
||||
var source = 'dd<a href="#"><b><c>haha</c></b></a><br>ff';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onIgnoreTag: function (tag, html, options) {
|
||||
debug(arguments);
|
||||
i++;
|
||||
if (i === 1) {
|
||||
assert.equal(tag, 'c');
|
||||
assert.equal(html, '<c>');
|
||||
assert.equal(options.isClosing, false);
|
||||
assert.equal(options.position, 17);
|
||||
assert.equal(options.sourcePosition, 17);
|
||||
assert.equal(options.isWhite, false);
|
||||
} else if (i === 2) {
|
||||
assert.equal(tag, 'c');
|
||||
assert.equal(html, '</c>');
|
||||
assert.equal(options.isClosing, true);
|
||||
assert.equal(options.position, 30);
|
||||
assert.equal(options.sourcePosition, 24);
|
||||
assert.equal(options.isWhite, false);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, 'dd<a href="#"><b><c>haha</c></b></a><br>ff');
|
||||
});
|
||||
|
||||
it('#onIgnoreTag - return new html', function () {
|
||||
var source = 'dd<a href="#"><b><c>haha</c></b></a><br>ff';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onIgnoreTag: function (tag, html, options) {
|
||||
debug(html);
|
||||
return '[' + (options.isClosing ? '/' : '') + 'removed]';
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, 'dd<a href="#"><b>[removed]haha[/removed]</b></a><br>ff');
|
||||
});
|
||||
|
||||
it('#onTagAttr - match attr', function () {
|
||||
var source = '<a href="#" target="_blank" checked data-a="b">hi</a href="d">';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onTagAttr: function (tag, name, value, isWhiteAttr) {
|
||||
debug(arguments);
|
||||
assert.equal(tag, 'a');
|
||||
i++;
|
||||
if (i === 1) {
|
||||
assert.equal(name, 'href');
|
||||
assert.equal(value, '#');
|
||||
assert.equal(isWhiteAttr, true);
|
||||
} else if (i === 2) {
|
||||
assert.equal(name, 'target');
|
||||
assert.equal(value, '_blank');
|
||||
assert.equal(isWhiteAttr, true);
|
||||
} else if (i === 3) {
|
||||
assert.equal(name, 'checked');
|
||||
assert.equal(value, '');
|
||||
assert.equal(isWhiteAttr, false);
|
||||
} else if (i === 4) {
|
||||
assert.equal(name, 'data-a');
|
||||
assert.equal(value, 'b');
|
||||
assert.equal(isWhiteAttr, false);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a href="#" target="_blank">hi</a>');
|
||||
});
|
||||
|
||||
it('#onTagAttr - match attr', function () {
|
||||
var source = '<a href="#" target="_blank" checked data-a="b">hi</a href="d">';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onTagAttr: function (tag, name, value, isWhiteAttr) {
|
||||
debug(arguments);
|
||||
return '$' + name + '$';
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a $href$ $target$ $checked$ $data-a$>hi</a>');
|
||||
});
|
||||
|
||||
it('#onIgnoreTagAttr - match attr', function () {
|
||||
var source = '<a href="#" target="_blank" checked data-a="b">hi</a href="d">';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
|
||||
debug(arguments);
|
||||
assert.equal(tag, 'a');
|
||||
i++;
|
||||
if (i === 1) {
|
||||
assert.equal(name, 'checked');
|
||||
assert.equal(value, '');
|
||||
assert.equal(isWhiteAttr, false);
|
||||
} else if (i === 2) {
|
||||
assert.equal(name, 'data-a');
|
||||
assert.equal(value, 'b');
|
||||
assert.equal(isWhiteAttr, false);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a href="#" target="_blank">hi</a>');
|
||||
});
|
||||
|
||||
it('#onIgnoreTagAttr - match attr', function () {
|
||||
var source = '<a href="#" target="_blank" checked data-a="b">hi</a href="d">';
|
||||
var i = 0;
|
||||
var html = xss(source, {
|
||||
onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
|
||||
debug(arguments);
|
||||
return '$' + name + '$';
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a href="#" target="_blank" $checked$ $data-a$>hi</a>');
|
||||
});
|
||||
|
||||
it('#escapeHtml - default', function () {
|
||||
var source = '<x>yy</x><a>bb</a>';
|
||||
var html = xss(source);
|
||||
debug(html);
|
||||
assert.equal(html, '<x>yy</x><a>bb</a>');
|
||||
});
|
||||
|
||||
it('#escapeHtml - return new value', function () {
|
||||
var source = '<x>yy</x><a>bb</a>';
|
||||
var html = xss(source, {
|
||||
escapeHtml: function (str) {
|
||||
return (str ? '[' + str + ']' : str);
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '[<x>][yy][</x>]<a>[bb]</a>');
|
||||
});
|
||||
|
||||
it('#safeAttrValue - default', function () {
|
||||
var source = '<a href="javascript:alert(/xss/)" title="hi">link</a>';
|
||||
var html = xss(source);
|
||||
debug(html);
|
||||
assert.equal(html, '<a href title="hi">link</a>');
|
||||
});
|
||||
|
||||
it('#safeAttrValue - return new value', function () {
|
||||
var source = '<a href="javascript:alert(/xss/)" title="hi">link</a>';
|
||||
var html = xss(source, {
|
||||
safeAttrValue: function (tag, name, value) {
|
||||
debug(arguments);
|
||||
assert.equal(tag, 'a');
|
||||
return '$' + name + '$';
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a href="$href$" title="$title$">link</a>');
|
||||
});
|
||||
|
||||
it('#stripIgnoreTag', function () {
|
||||
var source = '<x>yy</x><a>bb</a>';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTag: true
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, 'yy<a>bb</a>');
|
||||
});
|
||||
|
||||
it('#stripTagBody - true', function () {
|
||||
var source = '<a>link</a><x>haha</x><y>a<y></y>b</y>k';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTagBody: true
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a>link</a>bk');
|
||||
});
|
||||
|
||||
it('#stripIgnoreTagBody - *', function () {
|
||||
var source = '<a>link</a><x>haha</x><y>a<y></y>b</y>k';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTagBody: '*'
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a>link</a>bk');
|
||||
});
|
||||
|
||||
it('#stripIgnoreTagBody - [\'x\']', function () {
|
||||
var source = '<a>link</a><x>haha</x><y>a<y></y>b</y>k';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTagBody: ['x']
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a>link</a><y>a<y></y>b</y>k');
|
||||
});
|
||||
|
||||
it('#stripIgnoreTagBody - [\'x\'] & onIgnoreTag', function () {
|
||||
var source = '<a>link</a><x>haha</x><y>a<y></y>b</y>k';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTagBody: ['x'],
|
||||
onIgnoreTag: function (tag, html, options) {
|
||||
return '$' + tag + '$';
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '<a>link</a>$y$a$y$$y$b$y$k');
|
||||
});
|
||||
|
||||
it('#stripIgnoreTag & stripIgnoreTagBody', function () {
|
||||
var source = '<scri' + 'pt>alert(/xss/);</scri' + 'pt>';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTag: true,
|
||||
stripIgnoreTagBody: ['script']
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, '');
|
||||
});
|
||||
|
||||
it('#stripIgnoreTag & stripIgnoreTagBody - 2', function () {
|
||||
var source = 'ooxx<scri' + 'pt>alert(/xss/);</scri' + 'pt>';
|
||||
var html = xss(source, {
|
||||
stripIgnoreTag: true,
|
||||
stripIgnoreTagBody: ['script']
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, 'ooxx');
|
||||
});
|
||||
|
||||
it('cssFilter', function () {
|
||||
var whiteList = xss.getDefaultWhiteList();
|
||||
whiteList.div.push('style');
|
||||
assert.equal(xss('<div style="width: 50%; vertical-align: top;">hello</div>', { whiteList: whiteList }),
|
||||
'<div style="width:50%;">hello</div>');
|
||||
assert.equal(xss('<div style="width: 50%; vertical-align: top;">hello</div>', { whiteList: whiteList, css: false }),
|
||||
'<div style="width: 50%; vertical-align: top;">hello</div>');
|
||||
var css = { whiteList: xss.getDefaultCSSWhiteList() };
|
||||
css.whiteList['vertical-align'] = true;
|
||||
assert.equal(xss('<div style="width: 50%; vertical-align: top;">hello</div>', { whiteList: whiteList, css: css }),
|
||||
'<div style="width:50%; vertical-align:top;">hello</div>');
|
||||
});
|
||||
|
||||
});
|
||||
127
test/test_html_parser.js
Normal file
127
test/test_html_parser.js
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* 测试 html parser
|
||||
*
|
||||
* @author 老雷<leizongmin@gmail.com>
|
||||
*/
|
||||
|
||||
var assert = require('assert');
|
||||
var parser = require('../lib/parser');
|
||||
var parseTag = parser.parseTag;
|
||||
var parseAttr = parser.parseAttr;
|
||||
var debug = require('debug')('xss:test');
|
||||
|
||||
describe('test HTML parser', function () {
|
||||
|
||||
function escapeHtml (html) {
|
||||
return html.replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
|
||||
function attr (n, v) {
|
||||
if (v) {
|
||||
return n + '="' + v.replace(/"/g, '"e;') + '"';
|
||||
} else {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
it('#parseTag', function () {
|
||||
var i = 0;
|
||||
var html = parseTag('hello<A href="#">www</A>ccc<b><br/>', function (sourcePosition, position, tag, html, isClosing) {
|
||||
i++;
|
||||
debug(arguments);
|
||||
if (i === 1) {
|
||||
// 第1个标签
|
||||
assert.equal(sourcePosition, 5);
|
||||
assert.equal(position, 5);
|
||||
assert.equal(tag, 'a');
|
||||
assert.equal(html, '<A href="#">');
|
||||
assert.equal(isClosing, false);
|
||||
return '[link]';
|
||||
} else if (i === 2) {
|
||||
// 第2个标签
|
||||
assert.equal(sourcePosition, 20);
|
||||
assert.equal(position, 14);
|
||||
assert.equal(tag, 'a');
|
||||
assert.equal(html, '</A>');
|
||||
assert.equal(isClosing, true);
|
||||
return '[/link]';
|
||||
} else if (i === 3) {
|
||||
// 第3个标签
|
||||
assert.equal(sourcePosition, 27);
|
||||
assert.equal(position, 24);
|
||||
assert.equal(tag, 'b');
|
||||
assert.equal(html, '<b>');
|
||||
assert.equal(isClosing, false);
|
||||
return '[B]';
|
||||
} else if (i === 4) {
|
||||
// 第4个标签
|
||||
assert.equal(sourcePosition, 30);
|
||||
assert.equal(position, 27);
|
||||
assert.equal(tag, 'br');
|
||||
assert.equal(html, '<br/>');
|
||||
assert.equal(isClosing, false);
|
||||
return '[BR]';
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}, escapeHtml);
|
||||
debug(html);
|
||||
assert.equal(html, 'hello[link]www[/link]ccc[B][BR]');
|
||||
});
|
||||
|
||||
it('#parseAttr', function () {
|
||||
var i = 0;
|
||||
var html = parseAttr('href="#"attr1=b attr2=c attr3 attr4=\'value4"\'attr5/', function (name, value) {
|
||||
i++;
|
||||
debug(arguments);
|
||||
if (i === 1) {
|
||||
assert.equal(name, 'href');
|
||||
assert.equal(value, '#');
|
||||
return attr(name, value);
|
||||
} else if (i === 2) {
|
||||
assert.equal(name, 'attr1');
|
||||
assert.equal(value, 'b');
|
||||
return attr(name, value);
|
||||
} else if (i === 3) {
|
||||
assert.equal(name, 'attr2');
|
||||
assert.equal(value, 'c');
|
||||
return attr(name, value);
|
||||
} else if (i === 4) {
|
||||
assert.equal(name, 'attr3');
|
||||
assert.equal(value, '');
|
||||
return attr(name, value);
|
||||
} else if (i === 5) {
|
||||
assert.equal(name, 'attr4');
|
||||
assert.equal(value, 'value4"');
|
||||
return attr(name, value);
|
||||
} else if (i === 6) {
|
||||
assert.equal(name, 'attr5');
|
||||
assert.equal(value, '');
|
||||
return attr(name, value);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
});
|
||||
debug(html);
|
||||
assert.equal(html, 'href="#" attr1="b" attr2="c" attr3 attr4="value4"e;" attr5');
|
||||
});
|
||||
|
||||
it('#parseTag & #parseAttr', function () {
|
||||
var html = parseTag('hi:<a href="#"target=_blank title="this is a link">link</a>', function (sourcePosition, position, tag, html, isClosing) {
|
||||
if (tag === 'a') {
|
||||
if (isClosing) return '</a>';
|
||||
var attrhtml = parseAttr(html.slice(2, -1), function (name, value) {
|
||||
if (name === 'href' || name === 'target') {
|
||||
return attr(name, value);
|
||||
}
|
||||
});
|
||||
return '<a ' + attrhtml + '>';
|
||||
} else {
|
||||
return escapeHtml(html);
|
||||
}
|
||||
}, escapeHtml);
|
||||
debug(html);
|
||||
assert.equal(html, 'hi:<a href="#" target="_blank">link</a>');
|
||||
});
|
||||
|
||||
});
|
||||
250
test/test_xss.js
Normal file
250
test/test_xss.js
Normal file
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 测试XSS
|
||||
*
|
||||
* @author 老雷<leizongmin@gmail.com>
|
||||
*/
|
||||
|
||||
var assert = require('assert');
|
||||
var _xss = require('../');
|
||||
var debug = require('debug')('xss:test');
|
||||
|
||||
|
||||
function xss (html, options) {
|
||||
debug(JSON.stringify(html));
|
||||
var ret = _xss(html, options);
|
||||
debug('\t' + JSON.stringify(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
describe('test XSS', function () {
|
||||
|
||||
it('#normal', function () {
|
||||
|
||||
// 兼容各种奇葩输入
|
||||
assert.equal(xss(), '');
|
||||
assert.equal(xss(null), '');
|
||||
assert.equal(xss(123), '123');
|
||||
assert.equal(xss({a: 1111}), '[object Object]');
|
||||
|
||||
// 清除不可见字符
|
||||
assert.equal(xss('a\u0000\u0001\u0002\u0003\r\n b'), 'a\u0000\u0001\u0002\u0003\r\n b');
|
||||
assert.equal(xss('a\u0000\u0001\u0002\u0003\r\n b', {stripBlankChar: true}), 'a\r\n b');
|
||||
|
||||
// 过滤不在白名单的标签
|
||||
assert.equal(xss('<b>abcd</b>'), '<b>abcd</b>');
|
||||
assert.equal(xss('<o>abcd</o>'), '<o>abcd</o>');
|
||||
assert.equal(xss('<b>abcd</o>'), '<b>abcd</o>');
|
||||
assert.equal(xss('<b><o>abcd</b></o>'), '<b><o>abcd</b></o>');
|
||||
assert.equal(xss('<hr>'), '<hr>');
|
||||
assert.equal(xss('<xss>'), '<xss>');
|
||||
assert.equal(xss('<xss o="x">'), '<xss o="x">');
|
||||
assert.equal(xss('<a><b>c</b></a>'), '<a><b>c</b></a>');
|
||||
assert.equal(xss('<a><c>b</c></a>'), '<a><c>b</c></a>');
|
||||
|
||||
// 过滤不是标签的<>
|
||||
assert.equal(xss('<>>'), '<>>');
|
||||
assert.equal(xss('<scri' + 'pt>'), '<script>');
|
||||
assert.equal(xss('<<a>b>'), '<<a>b>');
|
||||
assert.equal(xss('<<<a>>b</a><x>'), '<<<a>>b</a><x>');
|
||||
|
||||
// 过滤不在白名单中的属性
|
||||
assert.equal(xss('<a oo="1" xx="2" title="3">yy</a>'), '<a title="3">yy</a>');
|
||||
assert.equal(xss('<a title xx oo>pp</a>'), '<a title>pp</a>');
|
||||
assert.equal(xss('<a title "">pp</a>'), '<a title>pp</a>');
|
||||
assert.equal(xss('<a t="">'), '<a>');
|
||||
|
||||
// 属性内的特殊字符
|
||||
assert.equal(xss('<a title="\'<<>>">'), '<a title="\'<<>>">');
|
||||
assert.equal(xss('<a title=""">'), '<a title>');
|
||||
assert.equal(xss('<a h=title="oo">'), '<a>');
|
||||
assert.equal(xss('<a h= title="oo">'), '<a>');
|
||||
assert.equal(xss('<a title="javascript&colonalert(/xss/)">'), '<a title="javascript:alert(/xss/)">');
|
||||
assert.equal(xss('<a title"hell aa="fdfd title="ok">hello</a>'), '<a>hello</a>');
|
||||
|
||||
// 自动将属性值的单引号转为双引号
|
||||
assert.equal(xss('<a title=\'abcd\'>'), '<a title="abcd">');
|
||||
assert.equal(xss('<a title=\'"\'>'), '<a title=""">');
|
||||
|
||||
// 没有双引号括起来的属性值
|
||||
assert.equal(xss('<a title=home>'), '<a title="home">');
|
||||
assert.equal(xss('<a title=abc("d")>'), '<a title="abc("d")">');
|
||||
assert.equal(xss('<a title=abc(\'d\')>'), '<a title="abc(\'d\')">');
|
||||
|
||||
// 单个闭合标签
|
||||
assert.equal(xss('<img src/>'), '<img src />');
|
||||
assert.equal(xss('<img src />'), '<img src />');
|
||||
assert.equal(xss('<img src//>'), '<img src />');
|
||||
assert.equal(xss('<br/>'), '<br />');
|
||||
assert.equal(xss('<br />'), '<br />');
|
||||
|
||||
// 畸形属性格式
|
||||
assert.equal(xss('<a target = "_blank" title ="bbb">'), '<a target="_blank" title="bbb">');
|
||||
assert.equal(xss('<a target = "_blank" title = title = "bbb">'), '<a target="_blank" title="title">');
|
||||
assert.equal(xss('<img width = 100 height =200 title="xxx">'),
|
||||
'<img width="100" height="200" title="xxx">');
|
||||
assert.equal(xss('<img width = 100 height =200 title=xxx>'),
|
||||
'<img width="100" height="200" title="xxx">');
|
||||
assert.equal(xss('<img width = 100 height =200 title= xxx>'),
|
||||
'<img width="100" height="200" title="xxx">');
|
||||
assert.equal(xss('<img width = 100 height =200 title= "xxx">'),
|
||||
'<img width="100" height="200" title="xxx">');
|
||||
assert.equal(xss('<img width = 100 height =200 title= \'xxx\'>'),
|
||||
'<img width="100" height="200" title="xxx">');
|
||||
assert.equal(xss('<img width = 100 height =200 title = \'xxx\'>'),
|
||||
'<img width="100" height="200" title="xxx">');
|
||||
assert.equal(xss('<img width = 100 height =200 title= "xxx" no=yes alt="yyy">'),
|
||||
'<img width="100" height="200" title="xxx" alt="yyy">');
|
||||
assert.equal(xss('<img width = 100 height =200 title= "xxx" no=yes alt="\'yyy\'">'),
|
||||
'<img width="100" height="200" title="xxx" alt="\'yyy\'">');
|
||||
|
||||
});
|
||||
|
||||
// 自定义白名单
|
||||
it('#white list', function () {
|
||||
|
||||
// 过滤所有标签
|
||||
assert.equal(xss('<a title="xx">bb</a>', {whiteList: {}}), '<a title="xx">bb</a>');
|
||||
assert.equal(xss('<hr>', {whiteList: {}}), '<hr>');
|
||||
// 增加白名单标签及属性
|
||||
assert.equal(xss('<ooxx yy="ok" cc="no">uu</ooxx>', {whiteList: {ooxx: ['yy']}}), '<ooxx yy="ok">uu</ooxx>');
|
||||
|
||||
});
|
||||
|
||||
// XSS攻击测试:https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
|
||||
it('#XSS_Filter_Evasion_Cheat_Sheet', function () {
|
||||
|
||||
assert.equal(xss('></SCRI' + 'PT>">\'><SCRI' + 'PT>alert(String.fromCharCode(88,83,83))</SCRI' + 'PT>'),
|
||||
'></SCRIPT>">\'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>');
|
||||
|
||||
assert.equal(xss(';!--"<XSS>=&{()}'), ';!--"<XSS>=&{()}');
|
||||
|
||||
assert.equal(xss('<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRI' + 'PT>'),
|
||||
'<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="javascript:alert(\'XSS\');">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=javascript:alert(\'XSS\')>'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=JaVaScRiPt:alert(\'XSS\')>'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=`javascript:alert("RSnake says, \'XSS\'")`>'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG """><SCRI' + 'PT>alert("XSS")</SCRI' + 'PT>">'), '<img><SCRIPT>alert("XSS")</SCRIPT>">');
|
||||
|
||||
assert.equal(xss('<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=javascript:alert('XSS')>'),
|
||||
'<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=javascript:alert('XSS')>'),
|
||||
'<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=javascript:alert('XSS')>'),
|
||||
'<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="jav ascript:alert(\'XSS\');">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="jav	ascript:alert(\'XSS\');">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="jav\nascript:alert(\'XSS\');">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC=java\0script:alert(\"XSS\")>'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="  javascript:alert(\'XSS\');">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRI' + 'PT>'),
|
||||
'<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>');
|
||||
|
||||
assert.equal(xss('<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>'),
|
||||
'<BODY onload!#$%&()*~+-_.,:;?@[/|]^`=alert(\"XSS\")>');
|
||||
|
||||
assert.equal(xss('<<SCRI' + 'PT>alert("XSS");//<</SCRI' + 'PT>'),
|
||||
'<<SCRIPT>alert(\"XSS\");//<</SCRIPT>');
|
||||
|
||||
assert.equal(xss('<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >'),
|
||||
'<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >');
|
||||
|
||||
assert.equal(xss('<SCRIPT SRC=//ha.ckers.org/.j'),
|
||||
'<SCRIPT SRC=//ha.ckers.org/.j');
|
||||
|
||||
assert.equal(xss('<IMG SRC="javascript:alert(\'XSS\')"'),
|
||||
'<IMG SRC=\"javascript:alert(\'XSS\')"');
|
||||
|
||||
assert.equal(xss('<iframe src=http://ha.ckers.org/scriptlet.html <'),
|
||||
'<iframe src=http://ha.ckers.org/scriptlet.html <');
|
||||
|
||||
// 过滤 javascript:
|
||||
assert.equal(xss('<a style="url(\'javascript:alert(1)\')">', {whiteList: {a: ['style']}}), '<a style>');
|
||||
assert.equal(xss('<td background="url(\'javascript:alert(1)\')">', {whiteList: {td: ['background']}}), '<td background>');
|
||||
|
||||
// 过滤 style
|
||||
assert.equal(xss('<DIV STYLE="width: \nexpression(alert(1));">', {whiteList: {div: ['style']}}), '<div style>');
|
||||
// 不正常的url
|
||||
assert.equal(xss('<DIV STYLE="background:\n url (javascript:ooxx);">', {whiteList: {div: ['style']}}), '<div style>');
|
||||
assert.equal(xss('<DIV STYLE="background:url (javascript:ooxx);">', {whiteList: {div: ['style']}}), '<div style>');
|
||||
// 正常的url
|
||||
assert.equal(xss('<DIV STYLE="background: url (ooxx);">', {whiteList: {div: ['style']}}), '<div style="background:url (ooxx);">');
|
||||
|
||||
assert.equal(xss('<IMG SRC=\'vbscript:msgbox("XSS")\'>'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="livescript:[code]">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<IMG SRC="mocha:[code]">'), '<img src>');
|
||||
|
||||
assert.equal(xss('<a href="javas/**/cript:alert(\'XSS\');">'), '<a href>');
|
||||
|
||||
assert.equal(xss('<a href="javascript">'), '<a href>');
|
||||
assert.equal(xss('<a href="/javascript/a">'), '<a href="/javascript/a">');
|
||||
assert.equal(xss('<a href="/javascript/a">'), '<a href="/javascript/a">');
|
||||
assert.equal(xss('<a href="http://aa.com">'), '<a href="http://aa.com">');
|
||||
assert.equal(xss('<a href="https://aa.com">'), '<a href="https://aa.com">');
|
||||
assert.equal(xss('<a href="mailto:me@ucdok.com">'), '<a href="mailto:me@ucdok.com">');
|
||||
assert.equal(xss('<a href="#hello">'), '<a href="#hello">');
|
||||
assert.equal(xss('<a href="other">'), '<a href>');
|
||||
|
||||
// 这个暂时不知道怎么处理
|
||||
//assert.equal(xss('¼script¾alert(¢XSS¢)¼/script¾'), '');
|
||||
|
||||
assert.equal(xss('<!--[if gte IE 4]><SCRI' + 'PT>alert(\'XSS\');</SCRI' + 'PT><![endif]--> END', {allowCommentTag: true}),
|
||||
'<!--[if gte IE 4]><SCRIPT>alert(\'XSS\');</SCRIPT><![endif]--> END');
|
||||
assert.equal(xss('<!--[if gte IE 4]><SCRI' + 'PT>alert(\'XSS\');</SCRI' + 'PT><![endif]--> END'), ' END');
|
||||
|
||||
// HTML5新增实体编码 冒号: 换行

|
||||
assert.equal(xss('<a href="javascript:alert(/xss/)">'), '<a href>');
|
||||
assert.equal(xss('<a href="javascript&colonalert(/xss/)">'), '<a href>');
|
||||
assert.equal(xss('<a href="a
b">'), '<a href>');
|
||||
assert.equal(xss('<a href="a&NewLineb">'), '<a href>');
|
||||
assert.equal(xss('<a href="javasc
ript:alert(1)">'), '<a href>');
|
||||
|
||||
// data URI 协议过滤
|
||||
assert.equal(xss('<a href="data:">'), '<a href>');
|
||||
assert.equal(xss('<a href="d a t a : ">'), '<a href>');
|
||||
assert.equal(xss('<a href="data: html/text;">'), '<a href>');
|
||||
assert.equal(xss('<a href="data:html/text;">'), '<a href>');
|
||||
assert.equal(xss('<a href="data:html /text;">'), '<a href>');
|
||||
assert.equal(xss('<a href="data: image/text;">'), '<a href>');
|
||||
assert.equal(xss('<img src="data: aaa/text;">'), '<img src>');
|
||||
assert.equal(xss('<img src="data:image/png; base64; ofdkofiodiofl">'), '<img src>');
|
||||
|
||||
// HTML备注处理
|
||||
assert.equal(xss('<!-- -->', {allowCommentTag: false}), '');
|
||||
assert.equal(xss('<!-- a -->', {allowCommentTag: false}), '');
|
||||
assert.equal(xss('<!--sa -->ss', {allowCommentTag: false}), 'ss');
|
||||
assert.equal(xss('<!-- ', {allowCommentTag: false}), '<!-- ');
|
||||
|
||||
});
|
||||
|
||||
it('no options mutated', function () {
|
||||
var options = {};
|
||||
|
||||
var ret = xss('test', options);
|
||||
console.log(options);
|
||||
assert.deepEqual(options, {});
|
||||
|
||||
var ret2 = new _xss.FilterXSS(options);
|
||||
console.log(options);
|
||||
assert.deepEqual(options, {});
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user