These days, storing and displaying what is visible in the UI and on receipts is highly standardized and regulated by industry standards like PCI DSS. And even when you save your card on an ecommerce website that strictly adheres to PCI DSS, your card can still be stolen – or obtained. As it happened with me.
PCI DSS is a widely known and implemented industry standard for defining minimum security measures that should be taken when handling sensitive banking data such as credit cards. When an account is breached, or credit card data is taken by a third party, this is the layer of protection available to the data, ensuring that the data is not completely available to the attacker, by restricting the storage of certain data by entities, limiting what marks are visible by masking in UI, receipts, logs and anywhere else.
+------------------------------------+
| |
| 1234 56** **** 7890 |
| |
| VALID THRU |
| 08/29 |
| |
| METIN OZYILDIRIM |
+------------------------------------+
What can you actually show with PCI-DSS4
- Primary Account Number (PAN) – PAN is hidden when displayed. BIN and last 4 digits can be displayed
- Cardholder Name – As per
- Service Code – As is
- Expiry date – As per
what you can’t show
- full track data
- Card verification code
- pin/pin block
That said, these are the minimum things an industry should keep in mind when designing their flows. But in practice, the nature of certification and the amount of testing required to become certified requires companies to implement only the minimum described in the standards. And when they are informed about the vulnerabilities caused by their behavior, they do not want to change because they have already understood enough for the certification process.
As a consumer, I thought I was protected; When I save my credit card to a European merchant worth a billion dollars, or when I buy something at the supermarket and ignore the receipt, but the reality is a little different.
story time
I have a virtual credit card with no limits, 2FA (3D Secure) enabled, and is only saved and used by very well-known merchants. But I received an SMS, attempting to purchase from the website on which I had saved my card. You know, it often happens when you use the same password everywhere, which is no longer the case for me but that was an account I set up a long time ago, it’s my fault. But upon receiving the SMS, I immediately logged in, changed the password, checked if something was purchased, the limits on my virtual card were significantly reduced. My card isn’t completely disabled, because, it hasn’t been compromised?
Or, I thought so. Later that day, about 6 hours after the initial breach, I suddenly received 3-4 3D secure SMS attempts from different merchants that I did not use. All unsuccessful attempts, but the data here is valuable for understanding how it happened.
A few minutes later, while I was calling my bank to completely disable that card, they used another merchant without 3D Secure; This time all the available limits (which I have reduced) with multiple payments have been withdrawn. This time the money is withdrawn to a market’s e-wallet, which allows you to withdraw cash from that market.
Honestly I’m impressed, it’s a well designed pipeline, with more unobtrusiveness than I expected. Finally, after my chargeback request, I got the money back from my bank. But what actually happened?
How did they do it?
Attackers broke into my account, I know that part. But what they got was minutes before I could respond. He tried to make a purchase by viewing the bank’s 3D Secure page, canceled the order and left. How much is it enough to buy from another merchant?
The data they captured in the purchase attempt is that the card is still usable (not cancelled), the bank name (from the 3D Secure page), my hidden credit card number and the full expiration date. Normally for my card purchases to be completed seamlessly, they must have the complete PAN number (16 digits one), expiry date, CVC2 number, my phone used for 3D Secure etc. They don’t have all these details, or so I thought.
pan number
Payment card number, primary account number (PAN), is a card identifier found on payment cards, such as credit cards and debit cards, as well as stored-value cards, gift cards, and other similar cards. In some cases the card number is called a bank card number. [wikipedia]
PANs have a certain level of internal structure and share a common numbering scheme set by ISO/IEC 7812. The parts of the number are as follows:
- Six- or eight-digit Issuer Identification Number (IIN)
- A variable length (up to 12 digits) personal account identifier
- A single check digit calculated using the Luhan algorithm
And PCI DSS says that the first 6 digits and the last 4 digits can be shown safely along with the expiration date, because the first six digits are not case sensitive, and the last four are not meant to discriminate. But then what is left? My card has 16 digits, the first six are known, the last four are known and because of the checksum 1 number out of 10 could be a valid credit card. These are 99.999 possible credit card numbers.
But My Card and Bank does not allow merchants to proceed payments using only credit card number, they must use at least PAN, expiry date and CVV. Some banks and payment gateways can process payments using only credit card number, this is another unbelievable thing for me. My bank rejects payments without these required values, but you know, it also tells you which part of the data was faulty. Response codes from payment gateway are something like this
- That is not a valid credit card
- that card has expired
- You got all the details correct but the CVV is not correct
Nonsense? It literally helps you force it. And you have to brute force only 99k numbers first then for CVV 999 times with some slow speed for second step and you have to get the card from masked PAN number. In my case the attackers did this in 6 hours using multiple endpoints stolen from multiple merchants that provide credit card verification. Similar to verification that tries to charge 1 USD to your card to validate your account and payment details. They found these APIs stolen from the register flows of some unrelated e-commerce applications.
So in practice, the attackers tested at a rate of 6 requests per second (about 2 requests per second per API). It is very hard to find out that rate from the merchants point of view, because the sources are changing through IP proxies, credit card numbers are not the same, the nature of the brute force and the very small rate of requests.
And it turns out there’s also a list of merchants that are exempt from 3D Secure content. They are therefore treated favorably by the bank, and can make payments and subscribe without 3D Secure, which in turn gives them liability in case of chargebacks.
It was my mistake to use an insecure password, but PCI DSS is not only for e-commerce, it also standardizes information to be disclosed on physical receipts. This happened to me due to account breach and it can happen to you too because you throw the receipt in the dustbin without destroying it.
what happened next?
I got the money back through chargeback in short time.
I talked to the merchant about how their credit card cash system was used to withdraw money from my credit card without my permission, they didn’t care. Instead told me to contact my bank.
I contacted the e-commerce website to find out how it makes this easier by highlighting the 10 characters of the credit card along with the expiry date. They did not acknowledge it as a vulnerability, instead stating that they intentionally designed it to match the standard (PCI DSS 3 and 4).
Then I got curious and explained the situation to people who write payment APIs and work in the payments industry, they weren’t surprised either; Instead they told me that there are traders who can do transactions even without expiry date. I think so, everyone knows it. People who build gateways, engineers, hackers.
This happened last year, and since then any party switching payments from credit card to Caste is no longer doing so without 3D Secure. My bank still has a generous rate limit for brute forcing CVC2 that temporarily blocks use of that card for a few minutes.
Reference
Wikipedia – Pan
PCI DSS v4.0.1
Pavel, my payment engineer friend
<a href