Skip to content
HelalStart a project

Card-testing attack on a WooCommerce store: how to stop it

Your orders page fills with small failed or pending orders, the declines keep coming, and your payment processor has sent a warning. New guest accounts appear with junk names.

Happening right now?

Skip the reading for now. Use the emergency page: it reaches me straight away, and I start with the first-hour steps.

Hundreds of small failed orders keep appearing

You open the orders page and it is full of orders you don't recognize. Most are failed or stuck in pending payment. They are small, often a single cheap product. The names look random, the emails are junk or belong to free mail services, and the billing addresses don't match the cards. They come in bursts, sometimes dozens in a few minutes, often at night in your time zone.

Your Stripe or other gateway dashboard shows a wall of declines with reasons like "incorrect CVC", "insufficient funds" or "card declined". New guest customers and accounts pile up. Then the email arrives from your processor about unusual activity or a high decline rate.

This is card testing. Someone is using your checkout to find out which stolen cards still work.

Why it happens

Stolen card details are sold in bulk, and many of the cards in a list are already dead. Before the buyer uses them for something valuable, they check them. The cheapest way to check a card is a small real payment attempt on a store that won't notice. A success means the card is live. A decline costs the attacker nothing.

WooCommerce stores get picked because:

  • The checkout accepts unlimited attempts. By default, nothing stops one visitor from submitting the checkout hundreds of times.
  • There are several ways in. The classic checkout form posts to ?wc-ajax=checkout. Block-based checkouts use the Store API at /wp-json/wc/store/v1/checkout. Scripts can call these directly without ever loading a page, so protection on the visible form alone does not cover them.
  • Guest checkout means no friction. No account and no history are needed.
  • Cheap products make good tests. A low-priced item keeps the test small.
  • Usernames are public. WordPress exposes usernames at /wp-json/wp/v2/users and through ?author=1 URLs unless you block them, which helps attackers target accounts.

None of this means your store is badly built. It means the defaults assume good faith.

What fixing it involves

I work in this order. The first two steps stop an active attack; the rest keeps it stopped.

1. Stop the bleeding at the edge

If the store is behind Cloudflare, I add rules before traffic ever reaches WordPress:

  • A rate limiting rule on POST requests to the checkout paths above, including /wp-json/wc/store/v1/checkout. A real customer submits checkout once or twice. A tester submits it over and over.
  • A WAF custom rule that shows a Managed Challenge to checkout requests that look automated: no session cookie from earlier browsing, odd user agents, or countries you don't ship to. On plans with Bot Management, bot score is the strongest signal here.
  • IP and ASN blocks for the worst sources, as a supplement.

The point is to block by behavior, not only by address. Testers rotate IPs constantly, so an IP list alone loses.

Without Cloudflare, a security plugin or your host's firewall can rate-limit those endpoints. WooCommerce also has built-in rate limiting for the Store API, but it is off by default and is switched on in code with the woocommerce_store_api_rate_limit_options filter. Some payment plugins add their own card-testing protection, such as a CAPTCHA on checkout; check what yours offers and turn it on.

2. Force card authentication

3D Secure asks the cardholder's bank to confirm the payment, usually through the banking app. A tester with a stolen card number can't pass it. With Stripe, Radar rules can request 3D Secure for risky payments. During an attack I set it to request it for every card that supports it, then relax it once things calm down. Which rules you can write depends on your Stripe plan, so check what your account allows. Other gateways have their own versions of this setting.

3D Secure adds a step for real buyers, so it is a lever to pull hard during an attack and ease off after.

3. Tighten the processor's fraud rules

In Stripe Radar, or your gateway's equivalent, I review the default rules and add blocks where the account allows: too many attempts from one IP or one email, CVC or postal code failures, and billing countries you don't serve. The processor sees patterns across many stores that you can't, so its fraud tools are worth using fully.

4. Block user enumeration

I close /wp-json/wp/v2/users to logged-out visitors and stop ?author= URLs from revealing usernames. This is not what stops card testing, but it removes an easy map of your accounts, and attackers who find one weak spot often probe for others.

5. Clean up the fake orders without emailing anyone

Filter the orders by status, date range and pattern, then bulk-cancel or trash them. Before you do, check WooCommerce, Settings, Emails. The "Cancelled order" and "Failed order" emails go to the admin by default, so pause those or expect a flood. Don't change these orders to Refunded or Completed, because those statuses can email the customer. Sending to fake addresses produces bounces, and bounces hurt your sending reputation for real customers.

Then remove the junk customer accounts the attack created. Look for accounts with no completed orders, registered in the attack window, with matching patterns in name or email.

If any test payment actually succeeded, refund it so the real cardholder doesn't have to file a dispute.

6. Talk to your processor

Reply to the warning. Say what happened, when it began, and what you have changed. Ask whether the decline rate or any disputes put the account at risk and what they want to see. Card networks track dispute rates, and processors watch both disputes and declines. Showing that you have acted makes restrictions less likely.

7. Monitor so the next wave is caught early

Card testers come back, often to the same store. I set alerts for failed payment spikes, for bursts of orders under a set amount, and for new accounts per hour, and I keep an eye on the firewall event log. Reviewing these weekly turns the next attack from a crisis into a firewall log entry.

If the attack came with other signs of a break-in, such as unknown admins or redirects, read what to do in the first hour after a hack. Ongoing protection like this is part of security, infrastructure and site care.

Related service: Security, infrastructure & site care

01 / Proof

Where I've done this

I handled a card-testing attack on a US subscription supplement store: firewall rules against bot traffic, forced card authentication, an API user-enumeration block and fake-order filtering.

US subscription supplement store

Live

Stopping a card-testing attack

Problem
Bots were testing stolen cards at checkout, creating failed orders and payment risk.
What I built
Firewall rules against bot traffic, forced card authentication, API user-enumeration block, fake-order filtering.
Outcome
Live in production; card-testing orders stopped reaching the gateway.
Stack
  • Cloudflare WAF
  • WooCommerce
  • PHP

02 / Questions

Questions owners ask

Will blocking the attacker's IP address stop it?
Rarely for long. Card-testing tools rotate through large pools of proxy and residential IP addresses, so each block buys minutes. Rules based on behavior hold up better: too many checkout attempts in a short window, checkout requests with no normal browsing before them, or payment calls from sessions that never loaded a product page. Use IP blocks for the worst offenders, but rely on rate limits and challenges.
Can the attack get my Stripe account closed?
It can put the account at risk. Processors watch decline rates and fraud on every merchant, and card testing pushes both up fast. Stripe may contact you, restrict payments or, in serious cases, review the account. Respond quickly, explain what you have changed, and keep the protections in place. A processor that sees you acting is far more patient than one that sees nothing change.
Should I turn off guest checkout?
It helps against some tools, but it adds friction for real buyers, and attackers can create accounts automatically. I treat it as a short-term option during an active attack, not the main defense. Rate limits, a challenge on suspicious traffic and 3D Secure do more with less cost to your conversion rate. Turn guest checkout back on once the attack has stopped.
Do I need to refund or contact these customers?
No. The orders are not real, and the names and emails usually belong to no one or to people whose cards were stolen. Failed orders took no money. If any test charge did succeed, refund it so the cardholder does not have to dispute it. Do not email the order addresses; it helps no one and the bounces hurt your email sending reputation.

Is it happening now?

Get emergency helpNot urgent? Start a project