In my previous post about NFC Contactless Cards, we had a brief introduction mentioning NFC payment methods, and how to implement APDUs commands to generate a connection to obtain basic information.

In this post, I will explain one of the most important attacks against NFC and contactless cards that many malicious attackers implement to obtain critical information. The techniques that I will write about are not limited and could be modified to work against different platforms or brands.

Also this post will try to clarify this debate:

In order to figure this out, we should be able to read the records for the SFIs. For reference, let me use the same image & idea from my previous NFC post:

fig7-4This is the main idea: “You can quickly select an ADF with the Application Identifier (AID). So we obtained the AID from the previous post: Application Identifier(AID = A0000000031010)

Within an ADF(Application Definition Files), you can select AEFs(Application Elementary Files) with the Short File Identifier (SFI).”

This is the tricky part: let’s say that we already have the AID(A0000000031010) which could be a VISA Debit/Credit contactless card; this gives us access to get information from the SFI, but we need to get somehow the “route” or id for the records. With the AID, we can narrow what kind of structure the card has. This changes depending of the card’s manufacturer(Visa, Mastercard, Amex…)

Adam Laurie implements in his library a brute force attack against the files/records:


This slideshow requires JavaScript.

We have two nested loops: 1..31 and inside 1..256. This means that the card could have 31 SFIs and 256 records inside each SFI. We are talking about 7650 possible combinations!

The read_record function creates a combined APDU command with the data of the two cycles to request data from the card.

When the variable sfi = 1 and p1 = 1:

READ_RECORD = [0x00, 0xb2] //Constant to read records

p2 = (1 << 3) + 4 // p2 = 12
le = 0x00
apdu = READ_RECORD + [p1,p2,le] // apdu = 0x00, 0xb2, 0x01, 0x0c, 0x00

With this APDU command, we are ready to request a record.

This attack with all different combinations could be effective when we do not have any previous information about the card, but in this case, we do. We know that it is a VISA Debit/Credit, and its AID is A0000000031010. So we can narrow our brute force range to do it in seconds. We know that the card is using the Visa payWave technology for contactless cards; as result, we can reduce dramatically our attack.

Peter Fillmore have some specific examples to make brute force attacks depending of the card technology payWave, paypass…:

Instead of checking for every combination, Peter knew where each card saves its records:

Screen Shot 2017-09-29 at 12.11.20 PM.png

Peter reduced drastically the search spectrum splitting the code in different files depending on the contactless technology. However, I implemented a different approach: just one file to attack all the “logic” SFIs positions. So let’s grab some information, running a brute forcing attack against processing options in Samsung Pay NFC.

Now the question: “It’s possible to downgrade NFC contactless card info to its plain magstripe info?”

I am going to use a Wells Fargo Credit Card to try to answer this question:

This slideshow requires JavaScript.

Reading the magstripe data with an USB card reader, we can get the track 1(made some modification to keep my card “safe”) but I left the discretionary(last) part of the magstripe:

%BXXXXX24505XXXXXX^GALVAN/SALVADOR M^XXXX201100001010000000816000000?

201 = Service Code
100001010000000816000000 = Original discretionary data

We will try to obtain this data from Wells Fargo Credit Card using the contactless technology with USB ACR122u:

Screen Shot 2017-09-29 at 9.44.38 PM

Some of the most important information are the Cardholder Name(5f20) and the Discretionary data(9f1f):
5f20 Cardholder Name(17 bytes): GALVAN/SALVADOR M
9f1f Track 1 Discretionary Data(24 bytes): 100001010000000138000000

Original track 1:
%BXXXXX24505XXXXXX^GALVAN/SALVADOR M^XXXX201100001010000000816000000?

With the new Cardholder/discretionary data, we are just 3 digits away from the original track 1!
%BXXXXX24505XXXXXX^GALVAN/SALVADOR M^XXXX201100001010000000138000000?

So how we can get the original 3 digits?
How the cryptogram plays its role?

We should discuss these questions in a future post.