Strange Payment Gateway

  1. Am I being overly paranoid or do I have a genuine concern?

You have a genuine concern. Something is not right here.

  1. Is it normal for a gateway provider to obfuscate their code like this?

Obfuscation is not, all by itself, abnormal. However, at the point they're trying to open localhost connections to RDP, VNC, and other ports, that's not obfuscation, that's completely inappropriate and malicious.

  1. Should I advise my client to immediately change supplier?

I would advise your client that the code provided for integration appears to be malicious and that you cannot assume the supplier is either a) legitimate or b) capable of securing their business (and by extension, your client's). In addition, the supplier does not appear to integrate properly into a secure purchasing environment (the http: only js link), which calls into question their appropriateness even if legitimate.

As per @JaimeCastells's comment to the question, there is no "payforasia" service provider listed at http://www.visa.com/splisting/searchGrsp.do. That could mean they're doing business under that name but are certified under a different name, or it could mean they're a "Level 2 Service Provider". Neither of those options is reassuring, quite frankly.

  1. Should I walk away and chalk it up to experience?

If the client wants to continue with this supplier, I would definitely consider walking away. You can't make the client do the right thing, but you can choose not to be the one doing the wrong thing for them.

Javascript analysis

The intent of the obfuscated Javascript seems important. I've tried to untangle what's happening in the Javascript, and I'll link to readable partially de-obfuscated copies in this section.

Overall, my impression is that the level of obfuscation used in these scripts exceeds what is commercially reasonable and becomes suspicious as a result. The limited amount of inferences I can draw about what it does are not inline with normal payments processing. Lacking better information, I presume this is malicious javascript.

Here are files I'm looking at should you wish to explore the same question. These files have been run through the Online Javascript Beautifier and I've also used the Online Javascript Editor to pick apart bits of what the scripts do. You can see that even with the basic de-obfuscation applied, there's still a lot of obfuscation in place - check.js is full of arrays of integers which get processed by the code, and which are presumably more text or code to be executed.

There are at least four scripts involved:

  • csid.js
  • tags.js
  • check.js
  • checkcid.js

It's clear, for example, that the five ports the OP saw getting connection attempts are hardwired into check.js:

td_0a = ['REF:63333', 'VNC:5900', 'VNC:5901', 'VNC:5902', 'VNC:5903', 'RDP:3389'];

I will continue to poke at them, and may pastebin some copies, but I think it's reasonable to be distrustful of this code at this point.


A bit more info on that obfuscated javascript: They're using packer, a quite famous javascript compression method. Here's the unpacked js (you can also unpack it yourself here: http://dean.edwards.name/unpacker/ ):

var a = "";
try {
    var z = document.createElement('canvas');
    var A = z.getContext('2d');
    var B = 'http://security.tencent.com/';
    A.textBaseline = "top";
    A.font = "14px 'Arial'";
    A.textBaseline = "tencent";
    A.fillStyle = "#f60";
    A.fillRect(125, 1, 62, 20);
    A.fillStyle = "#069";
    A.fillText(B, 2, 15);
    A.fillStyle = "rgba(102, 204, 0, 0.7)";
    A.fillText(B, 4, 17);
    var C = z.toDataURL();
    C = C.replace("data:image/png;base64,", "");
    var D = atob(C).slice(-16, -12);
    a = b(D)
} catch (err) {};

function b(z) {
    var A, B, C = '',
        D;
    z += '';
    for (A = 0, B = z.length; A < B; A++) {
        D = z.charCodeAt(A).toString(16);
        C += D.length < 2 ? '0' + n : D
    };
    return C
};

function c(z, A) {
    var B = 180;
    var C = new Date();
    C.setTime(C.getTime() + B * 24 * 60 * 60 * 1000);
    document.cookie = z + "=" + escape(A) + ";expires=" + C.toGMTString()
};

function d(z) {
    var A, B = new RegExp("(^| )" + z + "=([^;]*)(;|$)");
    if (A = document.cookie.match(B)) return unescape(A[2]);
    else return null
};

function e() {
    var z = "";
    for (var A = 1; A <= 32; A++) {
        var B = Math.floor(Math.random() * 16.0).toString(16);
        z += B
    };
    z += new Date().getTime();
    return z.toUpperCase()
};
var f = "";
f = d("ccpspay");
if (f == null || f == '') {
    f = c("ccpspay", e());
    f = d("ccpspay")
} else {
    f += "OLD"
};
var g = "vduzzz8d";
var h = e();
var i = "";
i = navigator.systemLanguage || window.navigator.systemLanguage || navigator.language;
var j = "";
j = navigator.browserLanguage || window.navigator.browserLanguage || navigator.language;
var k = "";
k = navigator.appCodeName || window.navigator.appCodeName;
var l = "";
l = navigator.appMinorVersion || window.navigator.appMinorVersion;
var m = "";
m = navigator.appName || window.navigator.appName;
var n = "";
n = navigator.appVersion || window.navigator.appVersion;
var o = "";
o = navigator.cookieEnabled || window.navigator.cookieEnabled;
var p = "";
p = f;
var q = "";
q = a;
var r = "";
r = navigator.platform || window.navigator.platform;
var s = "";
s = navigator.userAgent || window.navigator.userAgent;
var t = "";
t = navigator.userLanguage || window.navigator.userLanguage;
var u = "";
u = String(window.screen.fontSmoothingEnabled);
var v = "";
v = String(window.screen.width + "x" + window.screen.height);
var w = "";
w = String(window.screen.colorDepth);
var x = new Array;
x[0] = i;
x[1] = j;
x[2] = k;
x[3] = l;
x[4] = m;
x[5] = n;
x[6] = o;
x[7] = p;
x[8] = q;
x[9] = r;
x[10] = s;
x[11] = t;
x[12] = u;
x[13] = v;
x[14] = w;
x[15] = new Date().getTimezoneOffset() / 60 * -1;
x[16] = window.location.host;
x[17] = h;
var y = x.join("&@");
document.getElementById("csid").value = y.toUpperCase();
document.write("<script type='text/javascript' src='https://h.online-metrix.net/fp/tags.js?org_id=" + g + "&session_id=" + h + "&pageid=1'></script>");
document.write("<noscript><iframe style='width: 100px; height: 100px; border: 0; position: absolute; top: -5000px;' src='https://h.online-metrix.net/tags?org_id=" + g + "&session_id=" + h + "&pageid=1'></iframe></noscript>");

While they may be a legit payment gateway (I don't know but they look pretty shady to me), they are filled with tracking tools. You may at least want to warn the client about that.


The behavior of the Javascript code you're analyzing is unusual, but plausible as part of an anti-fraud system.

This script is being used to evaluate the fraud risk of a client machine. As part of this evaluation, it is checking whether the machine may be configured as an open web proxy -- this is why the script is trying to open WebSockets to localhost on various ports. I have not seen this particular technique before, but I think it's rather clever actually. :) It avoids performing an invasive external port scan by having a client machine scan itself!

I didn't fully analyze the script myself, but based on some keywords in the script you linked, it appears that the script is also collecting various pieces of identifying information from the browser, such as the browser version, the system language, and various configuration options. Again, this is reasonable for an anti-fraud evaluation, and this vendor is not unusual in using these sorts of methods.