ASP防XSS代码
原作是在GitHub上,基于Node.js所写。但是。。ASP的JS引擎跟V8又有些不同。。于是,嗯。。
<% Function AntiXSS_VbsTrim(s) AntiXSS_VbsTrim=Trim(s) End Function %> <script language="javascript" runat="server"> //原GITHUB:https://github.com/leizongmin/js-xss/blob/master/index.js //过滤XSS攻击 @author 老雷<leizongmin@gmail.com> //转换到ASP by zsx(http://www.zsxsoft.com) function AntiXSS_run(html){ String.prototype.trim=function(){return AntiXSS_VbsTrim(this)}; return AntiXSS(html,AntiXSS_config); } var AntiXSS_noTag = function(text) { return text.replace(/</g, '<').replace(/>/g, '>'); }; function AntiXSS(html, options) { var whiteList = options.whiteList; var onTagAttr = options.onTagAttr; var onIgnoreTag = options.onIgnoreTag; var rethtml = ''; var lastPos = 0; var tagStart = false; var quoteStart = false; var currentPos = 0; var filterAttributes = function(tagName, attrs) { tagName = tagName.toLowerCase(); var whites = whiteList[tagName]; var lastPos = 0; var _attrs = []; var tmpName = false; var hasSprit = false; var addAttr = function(name, value) { name = name.trim(); if (!hasSprit && name === '/') { hasSprit = true; return; }; name = name.replace(/[^a-zA-Z0-9_:\.\-]/img, '').toLowerCase(); if (name.length < 1) return; if (whites.join().indexOf(name) !== -1) { if (value) { value = value.trim().replace(/"/g, '"e;'); value = value.replace(/&#([a-zA-Z0-9]*);?/img, function(str, code) { code = parseInt(code); return String.fromCharCode(code); }); var _value = ''; for (var i = 0, len = value.length; i < len; i++) { _value += value.charCodeAt(i) < 32 ? ' ': value.split("")[i]; } value = _value.trim(); var newValue = onTagAttr(tagName, name, value); if (typeof(newValue) !== 'undefined') { value = newValue; } } _attrs.push(name + (value ? '="' + value + '"': '')); } }; for (var i = 0, len = attrs.length; i < len; i++) { var c = attrs.split("")[i]; if (tmpName === false && c === '=') { tmpName = attrs.slice(lastPos, i); lastPos = i + 1; continue; } if (tmpName !== false) { if (i === lastPos && (c === '"' || c === "'")) { var j = attrs.indexOf(c, i + 1); if (j === -1) { break; } else { var v = attrs.slice(lastPos + 1, j).trim(); addAttr(tmpName, v); tmpName = false; i = j; lastPos = i + 1; continue; } } } if (c === ' ') { var v = attrs.slice(lastPos, i).trim(); if (tmpName === false) { addAttr(v); } else { addAttr(tmpName, v); } tmpName = false; lastPos = i + 1; continue; } } if (lastPos < attrs.length) { if (tmpName === false) { addAttr(attrs.slice(lastPos)); } else { addAttr(tmpName, attrs.slice(lastPos)); } } if (hasSprit) _attrs.push('/'); return _attrs.join(' '); }; var addNewTag = function(tag, end) { rethtml += AntiXSS_noTag(html.slice(lastPos, tagStart)); lastPos = end + 1; var spos = tag.slice(0, 2) === '</' ? 2: 1; var i = tag.indexOf(' '); if (i === -1) { var tagName = tag.slice(spos, tag.length - 1).trim(); } else { var tagName = tag.slice(spos, i + 1).trim(); } tagName = tagName.toLowerCase(); if (tagName in whiteList) { if (i === -1) { rethtml += tag.slice(0, spos) + tagName + '>'; } else { var attrs = filterAttributes(tagName, tag.slice(i + 1, tag.length - 1).trim()); rethtml += tag.slice(0, spos) + tagName + (attrs.length > 0 ? ' ' + attrs: '') + '>'; } } else { var options = { isClosing: (spos === 2), position: rethtml.length, originalPosition: currentPos - tag.length + 1 }; var tagHtml = onIgnoreTag(tagName, tag, options); if (typeof(tagHtml) === 'undefined') { tagHtml = AntiXSS_noTag(tag); } rethtml += tagHtml; } }; for (var currentPos = 0, len = html.length; currentPos < len; currentPos++) { var c = html.split("")[currentPos]; if (tagStart === false) { if (c === '<') { tagStart = currentPos; continue; } } else { if (quoteStart === false) { if (c === '<') { rethtml += AntiXSS_noTag(html.slice(lastPos, currentPos)); tagStart = currentPos; lastPos = currentPos; continue; } if (c === '>') { addNewTag(html.slice(tagStart, currentPos + 1), currentPos); tagStart = false; continue; } if (c === '"' || c === "'") { quoteStart = c; continue; } } else { if (c === quoteStart) { quoteStart = false; continue; } } } } if (lastPos < html.length) { rethtml += AntiXSS_noTag(html.substr(lastPos)); } return rethtml; }; var AntiXSS_config = { "whiteList": { // h1: ['style', 'class'], // h2: ['style', 'class'], // h3: ['style', 'class'], // h4: ['style', 'class'], // h5: ['style', 'class'], // h6: ['style', 'class'], hr: ['style', 'class'], span: ['style', 'class'], strong: ['style', 'class'], b: ['style', 'class'], i: ['style', 'class'], br: [], p: ['style', 'class'], pre: ['style', 'class'], code: ['style', 'class'], a: ['style', 'class', 'target', 'href', 'title' ,'rel'], img: ['style', 'class', 'src', 'alt', 'title'], div: ['style', 'class'], table: ['style', 'class', 'width', 'border'], tr: ['style', 'class'], td: ['style', 'class', 'width', 'colspan'], th: ['style', 'class', 'width', 'colspan'], tbody: ['style', 'class'], ul: ['style', 'class'], li: ['style', 'class'], ol: ['style', 'class'], dl: ['style', 'class'], dt: ['style', 'class'], em: ['style'], // cite: ['style'], // section: ['style', 'class'], // header: ['style', 'class'], // footer: ['style', 'class'], blockquote: ['style', 'class']//, // audio: ['autoplay', 'controls', 'loop', 'preload', 'src'], // video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width'] }, "onTagAttr": function(tag, attr, value) { if (attr === 'href' || attr === 'src') { if (/\/\*|\*\//mg.test(value)) { return '#'; } if (/^[\s"'`]*((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):/ig.test(value)) { return '#'; } } else if (attr === 'style') { if (/\/\*|\*\//mg.test(value)) { return '#'; } if (/((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):/ig.test(value)) { return ''; } } }, "onIgnoreTag": function(tag, html, options) { return AntiXSS_noTag(html); } }; </script>