Nowadays we can find RFID technology almost everywhere: in supermarkets (anti-theft), in assembly lines (identify & track items), in highways (tolls), in public transportation, in your passport and your credit card and it is also used by many companies and by hotels for access management.
This post is about the latter. Indeed, during my trips, should it be for business or for holidays, I have stayed in many hotels. Some of them were still using good old keys like you do at home, most of them still use magnetic cards and some were relying on RFID cards to give you access to your room. Unfortunately, the security level of such RFID access management highly depends on the manufacturer as we will see.
First, let’s begin with the tools I use. I started messing with RFID more than a year ago and today, I mostly rely on two tools:
- A proxmark3 which is a really awesome tool, able to deal with low frequency tags (120-135 kHz) and high frequency tags (13.56 MHz) but it’s pretty expensive, you have to handle external antennas and it relies on a dedicated client
- An OpenPCD 2 which only deals with a limited amount of high frequency tags but it’s opensource, credit card sized, and natively supported with libnfc and related tools.
So, basically, proxmark3 is useful when you are at home or at the office and it is mandatory for specific RFID technologies but usually, when I travel, I try to keep my hand-luggage as light as possible. That’s why I mostly rely on my Android tablet and why I avoid carrying specific cables (proxmark uses one of those between the main PCB and the antenna).
To still be able to mess with RFID/NFC technologies I might encounter while travelling, I cross-compiled a recent version of libnfc and mfoc to reasily crack Mifare Classic keys. There is also a tool called mfcuk but unfortunately this one had never worked so far… It only displays timing errors and never finishes. By googling, I don’t seem to be the only one encountering issues with it…
I won’t go into details about all kind of RFID tags that you might encounter but I am going to detail some of the NXP tags inside their Mifare family, which still seems the most popular ones for 13.56 MHz tags:
- Mifare Ultralight (64 bytes memory divided into 16 pages of 4 bytes, almost no protection)
- Mifare Classic (1KB or 4KB memory, divided into blocks, with r/w protection relying on two 6 bytes keys and custom cryptography algorithm called Crypto1 which is broken)
- Mifare Plus (2KB or 4KB memory, adds AES-128 cipher to the Mifare Classic tag)
- Mifare DESfire (2KB, 4KB or 8KB and uses DES cipher)
All those cards have a read-only area at the beginning of the memory that has been set by the manufacturer. More details about NXP Mifare family here.
OK, enough “theory” for now :)
So far, I encountered two manufacturers of RFID key systems dedicated to hotels:
- VingCard Elsafe, a Norwegian company
- Kaba Ilco, a Swiss or German company
VingCard seems to be quite an old player in hotel locks as I have already seen cards like those:
They might ring a bell for those of my readers who began working with computers when punch cards were the only way to interface with a computer ;-) But let’s go back to recent wireless technologies.
As far as I can tell, VingCard uses Mifare Ultralight tags for their locks. If you have read carefully the last paragraphs, you may rememer that this particular kind of token lacks security measures: anybody can freely read the content (64 bytes of data).
On the other side, Kaba is using Mifare Classic 1K cards for the customer’s keys and Mifare Classic 4K for manager’s keys (sort of master key + required to program customer’s keys). At least, on those, we found a bit of security. Unfortunately, crypto1, NXP’s cipher algorithm, is broken and you can recover all the keys in a matter of minutes (or something only a few seconds) with the tools I mentionned (mfoc / mfcuk or proxmark3).
My first goal to understand how those keys work was to dump them, several times, entering the room between dumping attempts just to check if it has a counter stored in it. At least, I expect to find, maybe encoded in a weird way:
- the room number
- start date of my stay
- duration of the stay
Also, to get extra dumps, I went back at the reception desk, asking them to program again my key because it was not working anymore or even asking them a new key because I seemed to have lost the first one (of course, I have given back both keys at checkout to avoid extra charges). Another thing to try when you have friends or family in the same hotel is to dump their keys too, specially if they are on the rooms next to yours (or at least on the same floor in case the floor is also encoded in the card). This way I was able bindiff the dumps and try to find useful stuff.
Let’s begin with VingCard. Here is the result while running vbindiff agains two different keys encoded for the same room:
That’s a lot of red! The first few bytes have to be different because it is the “unique ID” of the tag. But if we take a closer look at those dumps, we can see a pattern: one byte is repeated a lot on each dump in the red part. This value might be used to XOR the useful content. And the 4 final bytes might be a checksum value. Note also the constant 0x21 value across those dump at offset 0x13. Surprisingly, it matches the length of the big red block…
Let’s try again vbindiff after XORing the 33-bytes red memory block…
That’s definitely better! But we will have to found out later how this byte is computed… The next assumption we can take is for the three bytes located at 0x1F-0x21: on this particular hotel, I was given two room keys at once. So it might be the “key number” or something related.
Next step is to compare keys encoded for two different rooms within the same hotel (after XORing their respective blocks of course):
Bingo! We still have the same differences we have seen. Appart from that, only two bytes have changed between those cards. Those have to be the room number (or at least some sort of lock ID number).
Also, if you look carefully at the last two screenshots, you may notify that the byte at offset 0x1F only has 2 possible values so far: 0x42 or 0x82.
As it was a short stay (1 night), I wasn’t able to go deeper on those (trying to figure out the duration encoding and things like that). But remember, we still have to find how the XOR key is computed and what kind of checksum is used.
Well, for that part, I may disappoint you but no luck so far :( If any of my readers have a clue, please leave it in the comments and I will test it against all the dumps I have.
At the beginning I was talking about comparing the badly designed VingCard RFID system against Kaba Ilco’s one.
Long story short, by applying the exact same method, I can tell you that this one seems pretty good in several points:
- Mifare Classic keys (A and B) seem to be derived from the UID of the tag but despite a whole bunch of dumps, I wasn’t able to find an obvious algorithm
- While bindiff-ing two dumps, I always ended up with two completely different 16-bytes blocks even after having my key reprogrammed. Marketing brochures states that they use cryptography so my guess would be that this is an encrypted block, depending on the Mifare Classic 4K tag (the Manager key) that has been used to program it. Moreover, the brochure also states that the cipher key is renew every 30 days.
Going further on Kaba Ilco’s system would require to use the proxmark3 for passively sniffing RFID exchanges between the tag and the lock.
As a conclusion, we can say that every manufacturer states that his system is secure but one should really ensure that it actually is, either by auditing the system himself or by relying on a third-party actor that can do that.