Inside a WooCommerce Payment Skimmer: How Carders Moved From Phishing Pages to Checkout Backdoors
Cybercriminals are now targeting real e-commerce checkout pages, not just fake websites. This report reveals how a WooCommerce skimmer silently steals card details during genuine payments. Read the full report to understand the hidden risk.
Get the latest industry news, threats and resources.
Executive Summary
For years, the entry point for stolen card data was the fake page: bogus loan portals, reward-claim sites, parcel-redelivery lures, and lookalike bank logins that tricked victims into typing their card details into an attacker-controlled form. CloudSEK's HUMINT engagements with operators active on carding marketplaces (Savastan0, Cvvhub, Jerrys, Zillion, Proton, VClub, Pepe, CVV-focused shops, and several invite-only forums) indicate a clear shift in tradecraft. The more technical actors have largely abandoned standalone phishing for direct compromise of legitimate e-commerce sites gaining web-shell access, planting a backdoor in or around the payment flow, and silently harvesting card data from real customers during genuine purchases.
This post analyses one such artifact: a heavily obfuscated client-side payment skimmer recovered from a compromised WooCommerce store running WooCommerce Payments (Stripe). The skimmer impersonates the real Stripe payment element, validates cards in real time so the victim never suspects anything.
This analysis is defensive in intent. It describes behaviour, attack chain, indicators of compromise, and remediation so that merchants, hosting providers, and defenders can detect and remove this class of threat. It deliberately does not reproduce a working or reusable version of the malicious code.
Analysis
1. Background: The Move From Phishing to Checkout Compromise
Traditional card-phishing depends on convincing a victim to visit an attacker-controlled page and voluntarily enter data. That Spamming model has friction: domains get burned quickly, browser safe-browsing lists catch known lures, and conversion rates depend on the quality of the social-engineering hook.
Checkout compromise removes that friction entirely. Instead of luring victims to a fake site, the attacker brings the theft to where customers already trust the environment: a real store, a real cart, a real checkout. This is the Magecart model, named after the loose set of groups that pioneered injecting JavaScript skimmers into compromised online stores. Key advantages for the actor:
Trust is inherited: The victim is on a site they chose, with a valid TLS certificate and a familiar brand. There is nothing to "fall for."
Data is fresh and high-value: Cards are captured at the moment of a real purchase, paired with billing details and email, exactly the Fullz that sells at a premium.
Persistence and stealth: A well-hidden skimmer can run for months, and because the legitimate payment still completes, neither the customer nor the merchant notices anything wrong.
The data harvested this way feeds directly into the same deep, dark, and surface-web carding shops that previously relied on phishing dumps.
DOM overlay impersonating the genuine Stripe payment element
3. Technical Analysis (Behavioural)
The following describes what the code does at a behavioural level, the understanding a defender needs to detect and remediate it. Implementation detail that would aid reproduction has been intentionally omitted.
E-Commerce Payment Skimmer - Attack Workflow
3.1 Obfuscation and string hiding
The script opens with a large array of string fragments that is rotated at load time, plus a lookup function that maps numeric indices back to those strings. Every meaningful identifier, element IDs, event names, error messages, target selectors is referenced through this lookup rather than appearing as plain text. This is the standard output shape of common JavaScript obfuscators and is designed to defeat naive grep-based scanning and casual code review.
On top of that, the sample carries a custom encoding layer built from Base64 plus URL escape/unescape and a per-character string-reversal helper. Two large encoded blobs are embedded in the string table; these decode to the markup and styling for the fake payment form (see 3.3). A defender should treat the presence of multi-stage, self-rolled string encoding inside a checkout script as a strong red flag in itself, legitimate payment libraries do not hide their own DOM.
3.2 Platform targeting
The skimmer specifically keys off WooCommerce Payments. It looks for the Stripe payment container on the page (the wcpay-payment-element / StripeElement node) and only activates when it finds a checkout that matches. This narrow targeting reduces noise and keeps the skimmer dormant on pages where it would be visible or useless.
3.3 Fake form injection ("overlay" technique)
Rather than reading the real Stripe iframe (which is cross-origin and protected), the skimmer builds its own look-alike form and places it over or in line with the genuine payment area. The decoded blobs contain the HTML and inline CSS for this fake form, styled to match Stripe's own field layout (card number, expiry, CVC), down to placeholder behaviour and focus styling.
The attacker-controlled fields are identifiable by a consistent naming convention input IDs suffixed with _sb (for example, the card-number, expiry, and security-code fields). Because these are first-party DOM elements injected into the page, the data typed into them is fully readable by the attacker's script, unlike the real, sandboxed Stripe iframe.
3.4 Real-time validation to avoid suspicion
The most "professional" aspect of this sample is how hard it works to feel legitimate. It re-implements the same client-side checks a real checkout performs:
Card brand / BIN detection. It inspects the leading digits to classify the card (e.g., the 4, 5, 34/37, 6011/65, 2-series ranges) and adjusts expected length and CVV length accordingly, so an Amex shows a 4-digit security code and a 15-digit PAN, etc.
Luhn checksum. It runs the standard mod-10 Luhn algorithm so an obviously invalid number triggers the same "card number is invalid" message a genuine form would show.
Expiry validation. It validates month range and checks the expiry against the current month/year, rejecting expired or impossible dates.
The effect is that the victim experiences an entirely normal-feeling checkout field that formats as you type, friendly inline errors, correct masking while every keystroke is being captured. There is no visual tell.
3.5 Stealth and footprint disguise
The skimmer actively works to look like benign site infrastructure:
It stores state in localStorage under keys crafted to resemble marketing/analytics artifacts (for example, a fbpixel_-style prefix), so a quick look at browser storage doesn't stand out.
It sets a Google Analytics opt-out flag (ga-disable-G-3SDSS99J4N), suppressing GA collection on the page likely to reduce the chance that the merchant's own analytics records anomalous behaviour around the injected element.
It uses a stored marker to deduplicate victims, avoiding repeat exfiltration of the same card so that outbound traffic stays minimal and patternless.
3.6 Data collection and exfiltration
Once a card passes the skimmer's own validation, the script also pulls the customer email from the checkout and bundles it with the captured PAN, expiry, and CVV. The combined record is passed through the custom encoding layer (Base64 + escape + reversal) and transmitted to an attacker-controlled collection endpoint. Encoding the payload helps the exfil traffic blend into ordinary-looking query strings or beacon requests and evade simple string-matching DLP rules.
4. Reconstructed Attack Chain
Based on the sample and corroborating HUMINT, the end-to-end operation typically follows this sequence:
Initial access: The actor gains a foothold on the store most commonly via a vulnerable or outdated plugin/theme, exposed admin credentials, or a known CMS vulnerability and drops a web shell.
Persistence / backdoor: Using the web shell, the actor plants a backdoor and positions code so that it executes on the checkout page (injected into a theme file, a plugin, the database, or loaded from an attacker-controlled host).
Skimmer delivery: The "sender.js" skimmer analysed here is served to checkout visitors. It lies dormant until it detects the WooCommerce/Stripe payment element.
Harvest: Real customers complete genuine purchases. The skimmer captures card + email in parallel with the legitimate transaction; the order still goes through.
Exfiltration: Encoded records are sent to the collection endpoint, deduplicated per victim.
Monetisation: Fresh, validated cards with billing context are sold on carding marketplaces and forums.
Because step 4 never breaks the customer experience, dwell time is often measured in months.
5. Indicators of Compromise (IOCs)
These indicators are drawn directly from the analysed code. Treat them as behavioural/host indicators rather than a definitive signature, as actors rotate IDs and endpoints frequently.
Suspicious DOM elements injected at checkout
Card/expiry/security inputs with an _sb suffix in their IDs that are not part of the genuine WooCommerce/Stripe markup.
A duplicate or overlaid payment form appearing alongside the real wcpay-payment-element / StripeElement.
Browser storage artifacts
localStorage keys mimicking pixel/analytics naming (e.g., a fbpixel_-style prefix) that the site's real tooling does not set.
A victim-deduplication marker key with no legitimate purpose.
Analytics tampering
An unexplained ga-disable-G-XXXXXXXXXX flag being set on the checkout page (observed value referenced a measurement ID of the form G-3SDSS99J4N). The merchant should confirm whether that GA property is even theirs.
Script characteristics
Heavily obfuscated JavaScript loaded into the checkout context, containing a rotated string-array, a custom Base64+escape+reverse decoder, and embedded encoded blobs that decode to form HTML/CSS.
Client-side re-implementation of Luhn validation and BIN/brand detection inside a script that is not the official Stripe/WooCommerce library.
Network
Outbound requests from the checkout page to a domain unrelated to Stripe, the payment processor, or the merchant's own analytics, especially carrying long encoded query strings or beacon payloads.
6. Detection Guidance
For merchants and platform operators
Client-side / page integrity monitoring: Deploy tooling (or a Content Security Policy with reporting) that alerts on any new or changed script on the checkout page. Magecart-class skimmers live or die by going unnoticed in the front end.
Content Security Policy (CSP): Restrict script-src and connect-src to known-good origins so injected scripts cannot freely exfiltrate to arbitrary domains; use report-uri/report-to to surface violations.
Subresource Integrity (SRI): Pin hashes on third-party scripts so tampered or swapped files fail to load.
File Integrity Monitoring (FIM): Watch theme files, plugin directories, and core files for unexpected modifications, a primary persistence location for the backdoor that serves the skimmer.
Database review: Check wp_options, widget/header-footer injection plugins, and post content for injected <script> blocks or base64 blobs.
Analytics anomaly checks: Investigate any ga-disable-* flags set client-side and reconcile GA property IDs against your own.
Synthetic checkout testing: Periodically run an automated checkout in an instrumented browser and diff the DOM and network calls against a known-good baseline.
For consumers
Be alert if a checkout asks you to re-enter full card details in an unusual second form, or if the payment fields behave differently than the processor's normal hosted form.
Prefer wallet/tokenised payment methods (Apple Pay, Google Pay, PayPal) where the card is never typed into the page.
Use virtual or single-use card numbers for online purchases where your bank supports them, and enable transaction alerts.
Detection & Hunting Snippets
The following are defensive; they help locate this skimmer family, not run it. Tune the strings to your environment before deploying.
Browser-side: scan a live checkout for the rogue overlay
Run in DevTools on a suspect checkout (or wrap into a synthetic-monitoring step):
On-disk: grep theme/plugin/core files for the obfuscation signature
Database: hunt WordPress/WooCommerce for injected loaders
YARA: identify the skimmer in files/memory
rule ecommerce_skimmer_wcpay_sb_overlay
{
meta:
description = "Heuristic for WooCommerce/Stripe overlay skimmer (sender component)"
// targeting + at least one rogue field + an obfuscation/stealth trait
$target and any of ($field*) and 2 of ($ga, $rotator, $b64helpers)
}
7. Beyond Stripe: How the Same Tradecraft Adapts to Other Gateways
The sample analysed above targets WooCommerce Payments (Stripe), but it would be a mistake to read this as a Stripe-specific problem. It is a class of threat. Critically, the first two stages of the attack chain initial access and the web-shell/backdoor that achieves persistence are completely gateway-agnostic. Once an actor controls code execution on the checkout page (or server-side rendering of it), the only thing that changes from one processor to the next is how the card data is captured in stage 4. And that, in turn, is dictated by the gateway's legitimate integration model. Understanding that model tells a defender exactly where to watch.
7.1 Two integration models, two capture strategies
Most modern gateways fall into one of two patterns, and skimmers adapt accordingly:
Hosted / sandboxed fields (iframe-isolated): Stripe Elements, Braintree Hosted Fields, Adyen Web Components/Drop-in, Square Web Payments SDK, Authorize.Net Accept.js. The card data lives inside a processor-controlled iframe the merchant page legitimately cannot read. Because the data is out of reach, skimmers respond by overlaying a look-alike first-party form (exactly what our sample does) or by hooking the tokenisation callback that returns a token/nonce.
Redirect / hosted-page or direct-post flows: some PayPal flows, older Authorize.Net-style direct post, and many regional gateways that redirect to a hosted payment page. Here the in-page card surface may be minimal, so attackers favour server-side interception before the redirect or injecting an extra capture step ahead of the hand-off.
The single most reliable, gateway-independent tell for a defender is therefore: a first-party <input> collecting a full PAN/CVV where a sandboxed iframe should be, combined with an outbound connection to a domain that is not the processor.
7.2 Defensive cues per gateway
The notes below are detection-oriented — what the legitimate flow looks like, and what to watch for. They are intentionally not implementation guidance.
Gateway
Integration model
Where card data should live
Defender's top detection cue
Stripe Elements / WCPay
Hosted fields iframe
js.stripe.com iframe
Rogue first-party inputs (e.g. *_sb) beside the Stripe element; connecting to a non-Stripe host
Braintree
Hosted Fields iframe
Braintree iframes
Overlay form near the Braintree container; script hooking the tokenize() callback
Adyen
Web Components / Drop-in
Adyen secured fields
Fake fields over the component; hooks on onChange / onSubmit component state
Square
Web Payments SDK
Square-tokenised fields
Rogue inputs; interception of tokenize() result before submit
Authorize.Net
Accept.js / hosted form
Client-side tokenised opaque data
Scripts reading the nonce / opaque-data before POST; unexpected connect endpoints
PayPal
Smart Buttons / redirect
PayPal-controlled UI / off-site
In-page "card" form appearing before redirect; tampered return URLs
Same front-end tells; backdoor often hidden in core_config_data, layout XML, or a fake module
7.3 Why one set of controls covers them all
The reassuring corollary is that defence does not need to be re-invented per gateway. Because every variant ultimately has to (a) present a capture surface in the page or server flow and (b) move the stolen data to an attacker endpoint, the same handful of controls catch the whole class:
CSP connect-src / script-src scoped to the real processor's domains blocks the exfil beacon and surfaces violations regardless of which gateway is in use.
Subresource Integrity on third-party scripts defeats the "swap the legitimate SDK for a trojanised copy" variant across all processors.
Client-side integrity monitoring + synthetic checkout diffing detects an unexpected first-party card field or a hooked tokenisation call no matter the brand.
Server-side file/DB integrity monitoring finds the backdoor that delivers the skimmer, which is where remediation must ultimately happen.
In other words: the capture technique is gateway-specific, but the initial access, the persistence, and the defences are not. A merchant who hardens the checkout as a monitored attack surface is protected against the Stripe variant and its Braintree, Adyen, Square, Authorize.Net, and PayPal cousins alike.
8. MITRE ATT&CK Mapping (Enterprise)
Tactic
Technique
ID
Initial Access
Exploit Public-Facing Application
T1190
Persistence
Server Software Component
Web Shell
T1505.003
Execution
Command and Scripting Interpreter
JavaScript
T1059.007
Defense Evasion
Obfuscated Files or Information
T1027
Defense Evasion
Impair Defenses: Disable or Modify Tools
Analytics opt-out
T1562
Collection
Input Capture
Web Portal Capture
T1056.003
Collection
Automated Collection
T1119
Exfiltration
Exfiltration Over Web Service
T1567
Remediation
If a store is found compromised:
Take the checkout offline or enable maintenance mode to stop further harvesting.
Find every location injecting the skimmer (files, DB, plugins, external loader) and the web shell that enabled it. Removing only the front-end script while leaving the backdoor in place guarantees reinfection.
Reset admin, FTP/SSH, database, and hosting-panel credentials, and rotate API keys. Assume the actor had broad access.
Update CMS core, plugins, and themes; remove abandoned/unused extensions, which are a frequent initial-access vector.
Implement CSP, SRI, FIM, least-privilege admin accounts, and 2FA on all administrative access.
Engage your acquirer/processor and follow PCI DSS incident obligations; notify affected customers as required by applicable law.
Review logs to scope when the skimmer was active and how many transactions were exposed.
Utilize CloudSEKto continuously monitor underground marketplaces, Telegram channels, and carding forums for emerging fraud activity targeting the platform.