Prevent Card Testing - Stripe Proform

For the last 3 days, some people have been using my s2member stripe form for card testing. Have you got any good idea how to best stop this without using a captcha?

I got the following message from Stripe:

Rest assured that Stripe remains secure. However, we’ve detected some fraudulent activity on your Stripe account called card testing. We wanted to provide insight into the specific type of card testing we’re seeing on your account in order to help you put effective mitigations in place. We need you to take immediate action to prevent it from continuing.
It looks like the card testers are using your integration to attach card information to a Customer. This confirms whether the card is valid, even without a payment. You can see the effects of this on your Dashboard by looking at the request logs in Developer > Logs[0] for excessive 402 errors on requests to attach card information to Customers using a secret key. Note that this includes some /v1/customers and /v1/payment_methods routes.
In order to combat the card testing, we recommend you add friction to your customer creation and/or customer card update features, making it more difficult for card testers to attach card information to new or existing customers. We also suggest implementing any other mitigations to prevent future card testing that you see fit. For a bit more context, we have documentation about card testing and how to prevent it here: https://stripe.com/docs/card-testing.
Card testing is an urgent issue for both your business and Stripe. Please reply to this message with a timeframe for implementing card testing mitigations on your integration within seven days. We understand that it may take you longer than seven days to implement card testing mitigations, but we ask that you reply with your plan and timeframe as soon as possible. If you haven’t responded within seven days, we may need to pause payouts on your account.
Feel free to reach out with further questions—we’re here to help.

— The Stripe Team

The strange thing is - in the 402 log - the IP address reported is always from my own server. So I don’t see how I can set up a good rule in the stripe radar. Anyone any ideas - Stripe will shut down my account if this continues to happen…

Sample Log - the IP address is from my own server:
Time

6/2/20, 4:17:21 AM

IP address

5.9.122.XX

Version

2019-10-08

Source

Stripe/v1 PhpBindings/7.4.0 WordPress s2Member Pro/200301 (https://s2member.com)

Related

customer — cus_HOC5rky9NHIHSL

Request query parameters

No query parameters

Request POST body

{

“customer”: “cus_HOC5rky9NHIHSL”

}

Response body

{

“error”: {

“code”: “incorrect_number”,

“doc_url”: “https://stripe.com/docs/error-codes/incorrect-number”,

“message”: “Your card number is incorrect.”,

“param”: “number”,

“type”: “card_error”

}

}

Okay - the rules are fine. The log is a bit bad. However I think this won’t be enough. It would be great if there was a way to show google recaptcha to anyone using an anonymous IP - this would surely get rid of the card testers.

Here is a list of radar rules that work well for me - and should help. But I’m afraid this won’t be enough without a captcha:

Block if payment has a risk score of 85 or higher
Block if payment matches one or more values in default Stripe block lists
Block if :declines_per_ip_address_daily: > 3
Block if :is_disposable_email: and :is_anonymous_ip:
Block if :declines_per_ip_address_daily: > 1 and :is_anonymous_ip:
Block if :is_disposable_email:
Block if :charge_attempts_per_card_number_hourly: > 1 and :is_anonymous_ip:
Block if :risk_score: > 10 and :is_anonymous_ip:
Block if :auths_per_ip_address_daily: > 3
Block if :auths_per_customer_daily: > 4
Block if :auths_per_card_number_daily: > 4
Block if CVC verification fails — 19 blocked

Note the CVC check helped me prevent 19 fraudulous charges by the card testers. So better not disable that rule. I had no legitimate payment blocked for it the last 6 months.

As I have root access to my server - is there any nginx rule that could help specifically for the Stripe proform url?
The card testers - and I guess most others will always use anonymous IPs - I don’t want to block them completely from accessing my websites - because e.g. users from China may have to use them.

Best would be rules for loading the credit card stripe popup - e.g. block it if there are more than 20 unsuccessful credit card attachements in the last 5 minutes. Block anonymous IP addresses from seeing that form - IF there have been more than 10 pageloads on that form in the last 10 minutes.
The card testers tested about 300.000 cards within 3 days - just to give a dimension of the problem. This will also lead to more declines of valid cards in the future. There really needs to be some sort of prevention of this happening by s2member (or a guide on how to prevent it gracefully - meaning not show every customer a google captcha but only select ones).

I always have people subscribe to level0 first so they can review free content and then when they are logged in I offer them a set of “pay for service” buttons to upgrade to a paid service. This is, by nature, the best rate limiter you can get.

Cannot do this, because one main point for payment is support via comments, so I can’t offer free level 0.

I’m waiting to see if the rules are enough to deter the card testers.it sure should help a bit.

I’m not sure what “support via comments” means. I assume you mean it is “pay per fix”?

You can always make it so that the “pay per fix” is only available to registered users (with or without s2member L0).

Out of curiosity what are “radar rules”?

Technical support via wordpress comments. It’s usually easy questions but 1year membership is cheap too. Old users don’t tend to have such questions,so not a big problem that even demoted they can post comments.

I really cannot offer free level 0. Also renewals are therefore cheaper, also after expiry and being demoted.

Google stripe radar. My rules above should not hurt at all - especially the ones about anonymous IP. They are really important and should come by default at stripe (but be deactivatable)

1 Like

Thanks for the Stripe Radar nudge. Interesting.

FYI - I wasn’t suggesting you have a free tier…just force everyone to register with your service to gain access to the paid “pay per fix”. By restricting your user base via registration you should eliminate virtually all your card testing traffic and without having to pay for Radar.

Radar rules are free. The problem is the stripe credit card form, it cannot be left without protection - because radar works only on actual payment, but testing of the card number it’s enough to attach a credit card without payment. I have to test if that is actually still possible with the current implementation. With the old popup it definitely was. I don’t know how it works now under the hood so to say. Is the customer at stripe created first by credit card attachment, then payment initiated, or is payment first.

Rules only work on payment, not on attaching a credit card to a customer, but credit card testing can be done without payment too by attachment of credit card!

So not sure if this part of the message was true: It looks like the card testers are using your integration to attach card information to a Customer. This confirms whether the card is valid, even without a payment. You can see the effects of this on your Dashboard by looking at the request logs in Developer > Logs[0] for excessive 402 errors on requests to attach card information to Customers using a secret key. Note that this includes some /v1/customers and /v1/payment_methods routes.

The reality is an exposed form is going to be leveraged for card testing. It’s luck of the draw whose form they choose to abuse. You happen to be unlucky. There are a million forms out there they could have chosen.

The only way to reduce the attack front is to force all users to register first and then offer them a payment form second. The registration verifies an email address which is, in effect, a throttle.

Well, I rather guess someone figured out a way to look for those s2member proforms. It happens on both of my domains!

I will see what stripe team says about it - My rules due block everything now - but the problem is still - people can become customer and add credit cards without any threshholds. I would need to find out some firewall or WP Cerber rules to block them - but cannot thing of any. They are using millions of gmail addresses - not sure if they actually exist or not. Had again a wave of 6000 payment attempts within 10 minutes (yes my server is very fast - so that’s why the must like it)

I’ve now set an nginx limit of 6 request per IP per minute for the checkout page. Plus blocked some IPs that were used in nginx. I hope they stop targeting me. It’s really a PITA.
I went through all the logs - and actually found one successful charge by the credit card testers - and refunded it with fraud notice. If this happens and you don’t refund quickly enough - you will face chargeback fees on top.

Even though this is all pretty unlikely - s2member should come with some intelligent blocking to prevent this. It will be much easier on the s2member side - than using server firewall rules.

s2member does have a foolproof card-testing option…force people to register first then offer a form to charge based on the service they select once their registration email check has passed.

I’m not sure why you keep wanting to take on the attackers directly. It can be a losing battle as you are finding:

  • The attackers rotate IP addresses
  • The attackers hijack legitimate accounts
  • The attackers spoof IP addresses
  • If you block an IP address you could be blocking an entire group of legitimate customers (ISP / corporate IP address blocks behind a proxy)

Just one man’s two cents worth :slight_smile:

It’s not possible with my business model at all. So that’s really not a solution!
The attackers always attack for like 30 minutes, it would be enough to have some intelligent firewall detect the attack and shut down the credit card form for non register users, the attackers then would move in quickly.

I will see how my nginx req limit works tonight, when I expect the next attack.

I guess I am missing the subtlety in your business model configuration. I always use registration to vet clients. It is the only real solution to attackers.

If you described your business model more clearly it would be easier to make suggestions. For example…if you are monitoring clients on WordPress.org and provide free help to a level and then want to charge the person for more advanced help you can provide them with a link to your s2member charge form with a single-use coupon. Write a simple s2member hook to only allow payment requests if a coupon is included.

The fact that your form is publicly accessible is a non-issue if you tokenize your manually approved transactions.

I really can’t - is is so hard to believe?
Anyway - the firewall settings did help a bit. So last night they tried again for about 3 hours - however only managed to get about 180x5 requests through - as nginx rate limiting blocked them out.

It’s too bad nginx rate limiting can only block by minute, I would need a rate limit per hour or even day. I will see if it makes sense ot maintain a local patched version of nginx.

Actually I wanted to block their IP directly - they don’t seem to be changing often at all, but made a small mistake there. Let’s wait another night. At least I’ve heavily reduced their requests - and the blocks are bombproof via stripe radar rules.

For anyone interested - here is my nginx rules - I’m pretty sure I’m not blocking any legitimate users so far - they did catch some bots however already according to my logs.:

nginx.conf - main part:
geo $limit {
default 1;
5.9.122.XX 0;
}
map $limit $limit_key {
0 “”;
1 $binary_remote_addr;
}
limit_req_status 403;
limit_req_zone $limit_key zone=two:5m rate=5r/m;

domain block:
location ~ /support/membership/ {
limit_req zone=two burst=1 nodelay;
limit_req_status 503;
try_files $uri $uri/ /index.php?$args;
}

Well - so far for 30 hours no single attempt for credit card testing. I did lock out one specific IP address in addition to the rules. It seems that was enough to have the bot/hackers decide to look for other targets.

There really should be some intelligent protection - but if you follow the steps above - it should be fine. The stripe radar rules I think everyone should implement.
Except: Block if payment has a risk score of 85 or higher - I have increased this to 90 - because it blocked my legitimate payments twice before (while 90 one would have passed). I do activate review payments above 80 however.