I found an API that exposed encrypted credit card numbers. Here’s how I cracked them to reveal the full card details.
While hacking on a private bug bounty program, I found a graphql endpoint that exposed way more information about logged-in users than it should have done. By playing with the ‘about me’ graphql API request I was able to guess and retrieve all the logged-in user’s stored values present in the database, not just those disclosed by the web app.
Using these guessed parameters, I was able to retrieve all credit cards added to a user’s account. This included: the cardholders name, their registered address, the expiry date of the card, the last 4 digits of the card, the type of card, and an encrypted version of the full credit card number.
The application allowed users to store up to 10 payment cards on their account for easier checkout when buying products and services. In order for the company to use them in future, I knew that they must be stored in a decryptable format. The challenge I set myself before submitting my report was to crack the encryption algorithm and view the raw card numbers.
Credit Card Numbers Explained
Credit and debit card numbers use an internationally recognised standard. A Payment Card Number (PCN) can be anywhere from 8 to 19 digits long and the first 6 to 8 digits are used to identify the bank which issued the card. This is known as the Issuer identification number (IIN). All American Express cards start with 34 or 37, all Visa cards start with a 4, etc.
There is also a range of card numbers that are reserved for testing purposes and which will never be assigned to real customers. (This is another bug you can test for while bug bounty hunting – can I make a purchase with a test-only card?). My personal favourite is for Visa: 4111 1111 1111 1111. Stripe has a list of test cards you can use anywhere and you can find more with a quick google search for “test payment card numbers”.
Finally, the majority of credit card numbers include a validity verification number using the Luhn algorithm. With this, the final digit of the card number is a check digit for all of the preceding numbers. For ‘4111 1111 1111 111X’ the check digit value is 1. For ‘4111 1111 1111 112X’ the check digit value is 9. You can play with this yourself using tools such as this one. As you can see, anyone can generate all possible card numbers for any given bank provided you know the prefix, the length, and whether or not it uses the Luhn algorithm. This is why you also need the card expiry date and CV2 numbers to make purchases.
Now that we’ve got a better understanding of credit card numbers, I’ll continue with my attack.
[Read more…] about Cracking Encrypted Credit Card Numbers Exposed By API