Detecting Credit Card Fraud – Frequency Algorithm
About 13 years ago I created my first integration with Authorize.net for a client who wanted to accept credit card payments directly on his website. The internet has changed a lot since then and the frequency of fraud attempts has increased.
One credit card fraud signature I identified while reviewing my server logs for one of my e-commerce websites was consistent. I refer to this is a shotgun attack, since the hacker sends through hundreds of credit card attempts. Here’s how it works and what to look for.
- All requests from a single throw away IP address
- Each request uses a different card
- Throwaway details are often used, including a generic email with some numbers in it
On the other hand, the overwhelming majority of other transactions were performed using a single card. Even if there were multiple attempts, they generally used one or two cards, but not more. I guessed I could use an algorithm that worked as follows for each transaction.
- Create a hash based on the last four digits on the card, the expiration date. This could use MD5, SHA or any other algorithm.
- Create a counter for the IP address that submitted that combination of values as represented by the hash and initialize to one
- For each transaction attempt, repeat step 1. If the hash matches what was stored in step 2 then don’t increment. If it doesn’t match, then increment the counter to two.
This process is repeated for every transaction attempt. Notice that a customer is free to continue submitting different addresses or CCV values for a single card without incrementing the counter. If the counter reaches a threshold, all transactions submitted from that IP address can be dropped. In my implementation I provided for an hour retention of data on a given IP address. The hour retention is reset every time a transaction is attempted from the IP address, which could keep it blocked indefinitely.
This credit card fraud prevention algorithm was implemented as a RESTful service using python bottle and memcached and provides less 100ms response times under heavy load and high concurrency.