Cracking the Waikato bus card system
The Waikato electronic card for buses - Busit
I recently published an application for reading the balance from a Busit card, the electronic ticketing system used in Waikato/Hamilton, New Zealand. One of the questions people have asked is what process did I use to get it working. This post hopefully provides some of the information required to build something like this for another city’s bus card system, or give a little more technical information for anyone interested.
What type of card are we dealing with?
The first thing when looking into a new card is to figure out what it actually is. Luckily there’s not a shortage of tools we can use for this these days, starting with your standard smart phone.
Most Android devices (and newer iPhones) have NFC built in, which allows reading one of the primary types of electronic cards. Most cards are split into low frequency (often just called RFID), and high frequency (often called NFC, though they’re technically RFID too). By attempting to read a card like this using your mobile phone, you can easily see which the system uses.
In our case, I opened up a free tool I often use for this kind of thing, NFC Tools, and scanned the Busit card:
The most important thing we can see on this screen is the Tag Type, listed as “NXP Mifare Classic 1k”. A little searching around the internet seems to indicate this is a common type of card for transportation systems, and more importantly for us, it’s considered very insecure.
Mifare Classic, and other bad decisions
Looking into the relevant Android APIs, it looks like we’re going to be able to develop something that can read and write information, but first, we’re going to need to know the keys in use for the Busit card.
The tool we’ve used so far (NFC Tools) hasn’t given us the option of cracking the keys for the Mifare Classic, so we’ll need to investigate another approach. In my case, I have access to a Proxmark3, which is capable of attacking the Mifare Classic protocol.
The Proxmark3 RDV2
Once I had the Proxmark3 set up and working on my PC, I was able to start probing the card and performing attacks. By running the command hf search
, I was able to see the Busit card I had has a weak PRNG. In my experience, most Mifare Classic cards have this same issue.
Now we have everything we need to begin an attack. To speed things up, we can check for default keys on the Busit card. People have contributed a large number of common keys to the Proxmark3 repository, so we might get lucky. We just run the hf mf chk * ? default_keys.dic
command, which means “hi-frequency, mifare, check every sector and every slot, using every default key from default_keys.dic”.
Turns out the keys for Busit don't really require cracking
Lo and behold, the Proxmark3 steps have been completely unnecessary! The Busit card uses the “default” keys of FFFFFFFFFFFF (which is the computer equivalent of setting your password to “1”).
With the keys obtained, we can begin looking at the data on the card and building our Android application.
Dumping our data
If you know the keys to a Mifare Classic card, there’s no limit to the ways you can read the data stored on it. In my case, since I wanted to build an Android application, I used my Android smart phone to dump all of the data from the card. I could have also used the Proxmark3 (with the hf mf dump
command) to see what data was stored on the card.
If you’re interested in the exact code used, check it out on GitHub.
Once I had the data, all that was left was to determine which of the sectors on the card corresponded with the balance. There can be some guess-work involved, but since I knew the balance on the card before I scanned it (from looking at my last travel receipt), I was able to have an idea of what I was looking for.
My last balance was $10.70, which can be stored a few ways by a computer. One might be to store it as a string, though that seems unlikely given strings are not very easy for a computer to do math on. Another might be a system called “floating point”, though this also seems unlikely, as floating point systems end up not being able to store a value like “$10.70” properly. The most likely option is just to store the number “1070”, using the standard computer number system of binary. In many dumps that people are looking at, such as the Proxmark3 Mifare dump format, you’re going to be seeing hexadecimal numbers instead. In our case, 1070 will show up as “ 42E”.
Once I knew what I was looking for, finding the right sector was easy. There was only one place where the value “42E”/”1070” was stored on the Busit card, which means it must be the balance. By noting down where it was, we can build an Android application which looks in this same place for every card and converts the value back to something human readable.
The latest source-code for the project is up on GitHub, so you can see how the Android application reads and decodes this value.
Now that we have read the value out, you might have a good guess at how to write the value. While I haven’t tested it, all signs point to it being trivial to modify the balance on your Busit card. That being said, there are many ways for you to be caught doing this kind of balance modification – someone, somewhere, is eventually going to notice a discrepancy in how much money they’re meant to be making vs how much they really are.
Previous work
Nothing in this post is new research, its all been done before.
Notable prior work that informed this post is is a similar set of problems discovered by AmmonRa, presented at Kiwicon, in the Christchurch bus system.
Other research of great value is the significant amount of effort put into defeating the security of the Mifare Classic system. Wikipedia is probably the best place to find a summary of relevant papers for those interested in learning more about this.
The Proxmark3 project has also been instrumental to my learning about different electronic cards and their security weaknesses.