EtherHiding Magecart Skimmer: Follow the Evidence

EtherHiding Magecart Skimmer: Follow the Evidence

An EtherHiding Magecart skimmer keeps its payload in smart contract storage on a public blockchain. The code that steals card data is not hosted on a bulletproof server in Moldova and it is not sitting in a file on your CDN. It is read out of a contract on a chain such as BNB Smart Chain, decoded in the browser, and run inside your checkout. Guardio Labs described the technique in October 2023 in the ClearFake campaigns, and Google Threat Intelligence Group published further analysis in October 2025 after state-aligned actors adopted it.

Most coverage treats it as a Web3 curiosity, or as part of a fake-browser-update story. This piece treats it as a checkout incident. The question is narrower and more practical: is the loader running on your payment page, where is the proof, and what do you preserve before you start deleting files.

Why a blockchain-hosted payload changes the investigation

A classic Magecart loader points at a domain. The domain has a registrar, a host, a hosting invoice and, usually, an abuse contact. You block it, you request a takedown, you watch the DNS records. That chain of custody is the backbone of a normal skimmer clean-up.

Contract storage removes all of it. There is no registrar. There is no host to petition. The contract address is a string on a public chain, and anyone with an RPC endpoint can read it.

Reading is the part that matters forensically. A read call of the kind used to fetch these payloads, an eth_call against a node, executes locally on that node. It costs nothing and it writes no transaction. So there is no gas payment to follow, no wallet to trace per retrieval, and no block explorer entry recording that your customer’s browser fetched the skimmer at 14:07 on a Tuesday. The only timeline of retrievals that exists anywhere is the one in your own logs, your own CSP reports and your own HAR captures. That is the single biggest practical difference, and it is why evidence preservation matters more here than in an ordinary clean-up.

There is one useful asymmetry. Writes are not free. Updating the stored payload requires a transaction, which costs gas and appears on-chain permanently. Once you have the contract address, a block explorer will show you when that contract’s storage was last written to. Those timestamps are frequently the best independent corroboration you will get for your own log window.

The flip side: the attacker can rewrite the payload between two page loads. A sample captured on Tuesday tells you what ran on Tuesday and nothing more. Two engineers examining the same checkout six hours apart can observe completely different behaviour, and both can be right. One clean scan is not proof of absence.

What has not changed is the way in. The attacker still needs code execution on your page before any of this works: a compromised supplier script, injected first-party JavaScript, or an unpatched platform. Storage moved. Delivery did not.

The request chain on a compromised checkout, stage by stage

Stage one: the loader lands in code you serve

It is small. Often twenty or thirty lines, frequently obfuscated, appended to the end of a legitimate bundle or dropped into a tag manager container as a custom HTML tag. In Magento and WooCommerce incidents it commonly appears in a theme template or a database-stored block rather than a file, which is why file integrity monitoring alone misses it.

Stage two: a read request goes out to an RPC endpoint

The loader POSTs JSON to a blockchain node over HTTPS. To most monitoring it looks like ordinary API traffic: a POST to a host you do not recognise, returning a blob of hex. No script tag, no external JavaScript file, nothing for a script-oriented scanner to flag.

Stage three: the response is decoded and executed in-page

The returned hex is decoded to JavaScript and run, normally through an evaluation call or an injected inline script. From this point the skimmer exists only in memory and in the live DOM. It may build keystroke listeners on the card fields, or draw a convincing fake payment form over a legitimate provider iframe.

Stage four: the data leaves

Exfiltration is usually a POST, an image beacon with the data base64-encoded in the query string, or a WebSocket. Conditional execution is near universal: the payload checks that the URL contains checkout, onepage, payment or similar before doing anything, and often checks that developer tools are closed. Browse the site as a tester and nothing happens. The same mechanics are covered in more depth in our walkthrough of the six stages of a JavaScript skimmer attack.

Where the evidence already sits in your own systems

CSP reports, and specifically connect-src

This is the loudest signal and the most commonly missed one. The payload arrives as data, not as a script resource, so a policy written only around script-src lets the fetch through without a murmur. The violation you want appears under connect-src.

A workable checkout policy looks something like this, with the provider and analytics endpoints named explicitly:

default-src ‘self’; script-src ‘self’ https://js.examplepsp.com; connect-src ‘self’ https://api.examplepsp.com https://region1.google-analytics.com; frame-src https://js.examplepsp.com; object-src ‘none’; base-uri ‘self’; report-uri /csp-report

Run that in report-only first and the loader’s call to a public node, something like bsc-dataseed.binance.org, arrives as a connect-src violation naming an origin nobody on your team configured. Browsers strip the path from cross-origin blocked URIs in many cases, so you get the origin rather than the full RPC request. The origin is enough. An RPC endpoint in your checkout’s connect-src reports has no innocent explanation. Our 14-day report-only rollout plan and the working checkout policy cover the mechanics of getting reports flowing without breaking payments.

Change detection under PCI DSS 11.6.1

Your tamper-detection records are the nearest thing you have to a before-and-after photograph. Two diffs matter. The script inventory on the payment page, where a new inline block or a changed bundle hash will show a timestamp. And the HTTP response headers served with checkout, because attackers who find a CSP in the way sometimes weaken or remove it first. A header diff showing your policy quietly dropped two days before the first fraud report is a date you can build an investigation around.

Repository, deployment and integrity evidence

Work out when the first-party file changed, under which account, and whether the change maps to a release. Modified timestamps that fall outside any deployment window are the clearest finding available. Compare the deployed bundle against the artefact your CI produced for that release; if they differ, the change happened after build, on the server or in the database.

Platform and admin trails

New or edited tag manager versions, with the publishing account and time. Template edits in the admin. Extension or plugin installs. Admin sessions from addresses or at hours that do not fit your team. Tag manager containers deserve particular attention because the change is invisible in your repository entirely.

The signal that usually arrives first

Issuer and acquirer fraud reports clustering on orders from a single date range beat every internal control, and they are how most merchants find out. If your acquirer sends you a common point of purchase notification, treat the date range in it as the anchor for everything above.

Which controls behave differently against this delivery route

Blocklists and takedown requests

There is nobody to write to. The payload is in contract storage on a public chain, and the chain is not going to remove it for you. You can block specific RPC endpoints at the network level, which helps marginally, but public nodes are numerous and the loader can be updated to use a different one. Takedown as a strategy does not apply here. Containment has to happen on your page.

Content Security Policy

CSP is the control that does the real work, provided it is written for data as well as for scripts. A tight default-src plus an allowlisted connect-src stops the fetch. Blocking inline execution closes the decode step. A policy that allows ‘unsafe-inline’ and ‘unsafe-eval’, which plenty of production checkouts still do for legacy reasons, gives the payload everything it needs.

Subresource Integrity

Wrong tool for this route. SRI pins the hash of third-party files you reference, and it is worth doing. It cannot help when the loader is injected into your own bundle or into an inline block, because there is no external file and no hash to compare. That is the same gap that let injected first-party code work in earlier Magecart incidents, and the delivery method has not improved SRI’s coverage of it.

Hosted payment fields and provider iframes

Moving the card inputs into a provider-hosted iframe takes the PAN out of reach at configuration level, and it remains the cheapest structural fix available. It is not immunity. An attacker with script execution on the surrounding page can hide the iframe and draw a convincing replica over the top, and can harvest name, address, email, phone and order contents regardless. Hosted fields reduce the blast radius considerably. They do not end the incident.

Triage: what to capture before you clean up

The instinct is to delete the malicious lines and push a fix. Resist it for twenty minutes. Contract storage can be rewritten, so evidence you do not capture now may not exist later.

  1. Record a full HAR of the checkout from a clean browser profile, with no extensions, noting the time and time zone. Complete a test transaction if you can do so safely in a sandbox. The HAR captures the RPC request and response that nothing else will.
  2. Save the loader source exactly as served, before formatting it. Extract the contract address, the RPC endpoint and the exfiltration host. Hash the modified files.
  3. Check the contract address against a public block explorer and note when its storage was last written. That gives you an independent date to set against your own logs.
  4. Freeze logs rather than letting them rotate: web server, CDN or WAF, admin access, deployment history, database change logs. An investigator appointed by your acquirer will ask for them, and short retention windows are a common and expensive problem.
  5. Decide whether to take the payment page down or switch to hosted fields while you work, and write down the reasoning with the time of the decision. Either choice is defensible. An undocumented choice is not.

Our guide to the first 24 hours after a checkout compromise sets out the wider sequence, including who to tell and in what order.

Reporting, compliance and a clean-up that sticks

Two PCI DSS 4.0 requirements apply whatever the payload is made of, and both stopped being future-dated on 31 March 2025. Requirement 6.4.3 asks for an inventory of every script on the payment page, with written justification and authorisation for each. Requirement 11.6.1 asks for detection of unauthorised change to the page’s scripts and HTTP headers, with alerting. We cover what 6.4.3 and 11.6.1 actually ask for in practice, and the current text is published by the PCI Security Standards Council.

Notify your acquirer early. Depending on volume and card brand rules, they may require a PCI Forensic Investigator, and the PFI will want the logs you preserved in the step above. Where customer personal data is affected, UK GDPR gives you 72 hours from becoming aware to notify the Information Commissioner’s Office. Those clocks run in parallel, not in sequence.

Then close the entry route. Deleting the loader removes the symptom and nothing else. Rotate admin and API credentials, including any service accounts with deploy rights. Audit extensions and remove the ones nobody can justify. Patch the platform. Review supplier scripts with the same standard you apply to your own code: Ticketmaster UK in 2018 was compromised through a third-party chatbot script, not through Ticketmaster’s code, and the ICO fined the company £1.25 million in November 2020. Two years later, Sansec reported around 2,000 Magento 1 stores compromised over a single weekend in September 2020, all through an unpatched platform. Supplier script, injected first-party code, unpatched platform. Those are still the three routes in.

Afterwards, keep report-only collection running alongside the enforced policy, re-baseline change detection against the cleaned page, and schedule repeat checks rather than a single sign-off scan. If the attacker still holds the entry route, the loader comes back with a different contract address and a different RPC endpoint, and the only thing that catches it is the connect-src report you are still reading.

The short version

The payload lives in contract storage, so there is nothing to take down and no transaction trail to follow. Your own logs, HAR captures and CSP reports are the timeline. Look for connect-src violations naming an RPC endpoint, not script-src ones. SRI will not help against an injected first-party loader. Hosted payment fields are still the cheapest structural fix, and still not complete cover. Capture everything before you clean, and close the way in rather than the file.

Frequently Asked Questions

What is an EtherHiding Magecart skimmer?

It is a card-skimming attack where the malicious JavaScript is stored in a smart contract on a public blockchain instead of on an attacker-controlled web server. A small loader on the compromised checkout reads the payload from a blockchain node, decodes it and runs it in the browser. The theft itself works the same way as any other payment page skimmer.

Can a Content Security Policy block an EtherHiding skimmer?

Yes, if the policy restricts where the page may connect to, not only where scripts may load from. The payload arrives as data from an RPC endpoint, so an allowlisted connect-src and a tight default-src are what stop it, together with blocking inline execution. A policy built only around script-src will let the fetch through silently.

Why can the malicious payload not simply be taken down?

Because there is no host or registrar behind it. The code sits in contract storage on a public chain that anyone can read, and the reads are free and leave no transaction record. You can block specific RPC endpoints, but the loader can be pointed at another node, so containment has to happen on your own page.

Do hosted payment fields protect a checkout from this kind of attack?

They remove the card number from your page, which is the single most useful structural change you can make. They do not prevent an attacker with script access from drawing a fake payment form over the provider iframe, or from harvesting name, address, email and order data from the surrounding page. Treat them as risk reduction, not immunity.

What should I capture before cleaning a compromised payment page?

A timestamped HAR of the checkout from a clean browser profile, the loader source as served, the contract address, the RPC endpoint, the exfiltration host and hashes of the modified files. Freeze server, CDN, admin and deployment logs instead of letting them rotate. Because contract storage can be rewritten at any time, evidence you do not capture now may be gone by the afternoon.