[homepage]  [search]


2009-03-10 20:24

Public transportation passes and their secrets


London, Moscow, Paris, Warsaw, Amsterdam, Venice...

As from January 31 2009, the "Carte Orange" commuter's card, along with its magnetic stripe ticket, is no longer in use on the greater Paris transportation network. The contactless "Navigo" pass has replaced it forever! After over ten years of hard work by the RATP, SNCF and Innovatron, this achievement takes place, however, much later than what has already been done elsewhere... At last, the time has come to explore these very special smart cards, with reasonable hope to clarify all their little mysteries that we were eager to investigate. Are they really able to trace all our whereabouts? Let's clear the matter up!

Indeed, "ticketing" is a long established reality of the public transportation world. London has been a pioneer with the early deployment of "Oyster" (Mifare technology), but historically speaking, everything started from France with the "Calypso" project. An original contactless technology developed by Innovatron was able to convince the RATP and SNCF, joined in the 1990s by transport operators worldwide. As soon as 2003, we were given a chance to try the product, courtesy of the "congress" badge of the "CARTES & IT Security" exhibition and its built-in Navigo pass, providing free access to public transportation. At this time, a magnetic ticket was still coming with this dual interface (contact and contactless) card, because quite a few stations were RFID enabled. This "environmentally correct" initiative came to an end in 2008, about one year after the inconspicuous launch of the (supposedly anonymous) "Navigo Découverte" pass in September 2007. No need, therefore, to reside in greater Paris to get a Navigo pass today, provided you pay the "cost" of € 5!

photo 4 Pass

For sure, time has come to put our hands on a contactless smart card reader, such as the exciting ACR122 from ACS, but sadly not to tamper with Navigo passes! In fact, they did not emancipate yet, from the old-fashioned and franco-french Innovatron communications protocol. Slightly different from the ISO14443 type B, it is, by the way its (incompatible) ancestor. But do'nt worry! In addition to their RFID antenna, Calypso (and therefore Navigo) passes are fitted with ISO7816 contacts, allowing us to perform the same tasks with any PC/SC smart card reader and the now usual BasicCard software kit. Fortunately enough, the latter proved to be compatible with the ACR122, helping a lot to explore (not without surprises!) disposable (or not) tickets based on the Mifare technology (London, Warsaw, Moscow, Venice, Amsterdam, and countless other cities throughout the world). Moreover, it is ready for NFC (Near Field Communication) technology, which is only waiting, before invading our daily lives, the wider availability of compatible mobile phones. Be sure that we are already working hard on this topic!

Classified specifications
By contrast with mobile telephony (SIM and USIM cards) or payment (EMV credit cards), most specifications for ticketing applications are classified. One must, therefore, individually qualify to access them (for interoperability purposes), a privilege that has been graciously granted to us. Let's comply, of course, with our NDA (Non Disclosure Agreements) and refrain from reproducing, here and there, sensitive parts of embargoed documents. Our feeling, however, is that their study would be more likely to deter potential fraudsters rather than to give them ideas... On the other hand, we believe that we have the legitimate right to provide our readers with homebrew software, allowing them to read the "public" contents of their own passes, so that they can determine by themselves whether or not they should feel comfortable. Given the high degree of standardization of Calypso passes, the methods which will be presented in the case of Navigo can be extrapolated, with little or no changes, to other "dematerialized" tickets (eg Weneo Pass from Neowave, a shining star of the "CARTES 2008" exhibition, now being tested by various rail networks). Basically, the memory of a Calypso pass (and therefore of a Navigo) is divided into a few perfectly defined areas, as detailed in the (public) commercial flyers from the various manufacturers (eg ASK with its TanGO family) or chip foundries (for example STMicroelectronics).
- identification of the badge and/or bearer;
- informations about the bearer;
- transportation journal;
- contracts;
- counters;
- "special events" area;
- "behavior and loyalty" area.
Of course, powerful (and secret!) cryptographic mechanisms protect the writing in these areas, and provide mutual authentication between the card and the terminal.

photo Pass CARTES 2003

Along with this ticketing application, some versions known as "multi-application" may include an electronic purse (EP) and/or a multi-purpose application (MPP), such as access to conferences at the CARTES exhibition. Necessary and sufficient to manage (by name or anonymously) public transportation uses like tube, regional trains, tram or bus, all these areas are not necessarily used on national railways. For example, the use of a Navigo pass to travel on the "Thalys" TGV is based solely on reading its serial number, the security functionality being provided (as well as the online booking) by a central computer system. Much the same for the rental of bikes in Paris (Vélib), where the Navigo pass is only a convenient means of identification, linked to a specific "paper" contract... The cryptographic functionality of the pass is not, in such cases, used at all (which is a pity!), and one might use, instead, virtually any other contactless badge. The number of contracts, however, would be quite sufficient for a possible international use: when will we see the acceptance of the Navigo pass in Brussels trams, or of the Belgian "Mobib" pass in the Paris tube?

The Navigo pass under scrutiny
Once again, a straightforward ZCBasic source code will prove sufficient for an almost exhaustive reading, using any common "contact mode" PC/SC reader (eg TeoByXiring). But the beauty of the thing is that, thanks to an additional SELECT command for the application with the 1TIC.ICA AID, the same BILLET.BAS program will also work with an ACR122 contactless reader, operating in PC/SC mode! Needless to say, this works pretty well with the "Weneo" tag, which was presented at the CARTES 2008 show, interestingly at the same time as the ACR122.

#Include CARDUTIL.DEF
#Include COMMERR.DEF
ComPort=101

Declare Command &H94 &HA4 SEL(S$,Disable Le)
Declare Command &H94 &HB2 RD(Lc=0,S$)
Declare Sub AFF(P$)
Public P$ As String

CLS:Print"TICKETING (c)2008 Patrick GUEULLE"
Call WaitForCard
ResetCard (P$):Call CheckSW1SW2
Print:Print
Print"ATR (Hist.): ";
FOR F=1 TO Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print:Print

P$="1TIC.ICA"
Call SEL(P1P2=&H0400,P$,Disable Le)

Print "Bearer Informations: ":Print
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(&H01)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
P$="":Call RD(P1P2=&H0104,P$,Le=29)
Call AFF(P$)

Print:Print"--- Transportation journal: press RETURN ---"
Input Z$:CLS
Print "Transportation journal: ":Print
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(&H10)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
For R=1 To 3
P$="":Call RD(P1=R,P2=&H04,P$,Le=29)
Call AFF(P$)
Next R

Print:Print"--- Contracts: press RETURN ---"
Input Z$:CLS
Print "Contracts 1: ":Print
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(&H20)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
For R=1 To 4
P$="":Call RD(P1=R,P2=&H04,P$,Le=29)
Call AFF(P$)
Next R

Print"Contracts 2:":Print
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(&H30)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
P$="":Call RD(P1P2=&H0104,P$,Le=29)
Call AFF(P$)

Print:Print"--- Counters: press RETURN ---"
Input Z$:CLS
Print"Counters:":Print
FOR C=&H2A To &H2D
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(C)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
P$="":Call RD(P1P2=&H0104,P$,Le=29)
Call AFF(P$)
Next C

Print:Print"--- Miscellaneous: press RETURN ---"
Input Z$:CLS
Print"Special events:":Print
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(&H40)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
P$="":Call RD(P1P2=&H0104,P$,Le=29)
Call AFF(P$)

Print"Behavior and loyalty:":Print
P$=Chr$(&H20)+Chr$(&H00)+Chr$(&H20)+Chr$(&H50)
Call SEL(P1P2=&H0800,P$,Disable Le):Call CheckSW1SW2
P$="":Call RD(P1P2=&H0104,P$,Le=29)
Call AFF(P$)

Print:Call WaitForNoCard

Sub AFF(P$)
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
Print M$;" ";
If F=16 Then Print
NEXT F
Print:Print
End Sub

Depending on the badges (existing or future, disposable or not) that we will explore, other AIDs might be tried: 3MTR.ICA, 1TIC.ICAn (with n ranging from 1 to 4), 2MPP.ICA, F0424D532E455469636B6574h (BMS.ETicket), OETP.ICA, etc. This may require, however, to also change the IDs of all or part of the files to read, which would lead us much too far, should we try to review in detail. For now, it should be noted, first of all, that only a file called "Bearer ID" cannot be read without the submission of a PIN code... that we do not have. Too bad, but in the specific case of a "Navigo Découverte" pass, if paid in cash, it could by no means (at least originally) contain identity data. Everything else is free to read, but "defined by the transport operator". This means that we will need some of Sherlock Holmes skills to analyse the results of our reading, the rule being not to refer to any classified specification. Let's take the example of the "badge informations" file, 29 bytes possibly being read as follows:

24 8A F8 AE 02 50 00 C6 02 18 00 44 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

In red, we notice 4 bytes that are also included in the ATR (answer to reset), which equal, as verified by ourselves, to the unique identifier of the pass (the one used to address it under the contactless protocol). In green, there is the same (standard) country code than in the credit cards: here, 0250 for France. Further, many 00 (or FF depending on the year) in these Navigos issued at the CARTES show... Now, let's compare the "Bearer information" between the same pass from the CARTES 2006 show, and a "Navigo Découverte" recently issued in early 2009:

24 B9 28 48 08 19 C2 0F BF F0 00 12 40 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

24 B9 28 48 08 03 A8 12 88 30 00 12 20 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

Only six bytes differ, despite the three-year interval between the issuance of the two cards, of which at least one is anonymous: rather insufficient to encode really personal details, but should you have any doubt, do feel free to watch periodically, since there is a lot of unused space...

Quite a sensitive subject: the famous "journal of transportation", in which the whereabouts of the commuter are reportedly recorded. Is Big Brother watching us? Every publicly available informations agree: This "black box" is limited to three recordings of 29 bytes each, the bare minimum to enable a guard to make sure that everything is in order. In practice, the latest three presentations of the pass before a validator are recorded. In London, well known as the heaven of videosurveilliance, an Oyster pass could go back much deeper in time: up to 25 events, which is infinitely more unpleasant... The interesting point is that these events are time-stamped, much like a paper ticket. Let's examine the three log entries of our own CARTES 2006 Navigo pass, which was only used to make a journey by regional train (SNCF then RATP) from Villepinte (Parc des expositions) to St-Germain en-Laye, on November 9 in the late afternoon:

38 3E 17 90 00 68 A2 90 19 14 98 91 20 00 88 40 00
00 00 00 00 00 00 00 00 00 00 00 00

38 3D F4 10 00 28 A2 88 14 64 98 00 80 40 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

11 1D 68 10 00 68 A1 88 18 10 82 81 D0 00 20 40 00
00 00 00 00 00 00 00 00 00 00 00 00

The first four bytes look like a "timestamp", and were invariably 11 1D 68 10 on all the unused passes that we ever examined. If we divide by 4 and convert into decimal both of 38 3E 17 90 and 38 3D F4 10 hex integers, we obtain respectively 235,898,340 and 235,896,068 seconds, counted from an initial time that the transport operator does not appear to be willing to disclose. No problem! The difference between these two values is 2272 seconds, roughly 38 minutes, which corresponds to the actual travel time when there is no waiting time at Châtelet-Les Halles. It seems, therefore, that basically, the events of entry into the network and of exit from it are recorded, the most recent events very logically overwriting the oldest ones. The few bytes that follow presumably identify the stations where the pass was waved, according to a coding which is also kept secret. Much may, however, appear to light if we give ourselves the trouble to consult this journal journey after journey, especially if we often use the same stations. But the main conclusion to be drawn from these initial investigations is that there is (at least here) no matter to worry about our private life, as long as we do'nt make these data available to untrusted parties!

Let's proceed to the "contracts" area, which still consists of 29 bytes records. In the case of the CARTES 2006 Navigo pass, the "congress" three days permit (18 to 20 November), valid for zones 1 to 4, is clearly represented by a block of 23 bytes, while the rest of the area being filled with 00s. It is highly probable that these data are encrypted, but nothing prevents one from trying to find some meaning (let's remember the horrific results it gave with the french health card) [FR].

5A 50 60 00 00 11 E0 14 8C 45 38 24 E0 F0 FD 38 30
0C 22 98 04 01 BC
00 00 00 00 00 00

The "Navigo Découverte", having not been loaded yet, seems to be "pre-formatted" but obviously, much like our sample Weneo, empty of any contract:

00 00 0F FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF

This is also the case of the following areas, except for the "behaviour and loyalty" record which, in our Navigo from CARTES 2006 (used just once), revealed four mysterious bytes:

1C 1F F2 10 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

In all of our new or unused Navigo passes, however, this area is completely blank:

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

It is here that we would most likely see, in our humble opinion, potentially disagreable data appear. The public transport operators, in fact, begin to sell to advertisers, the time during which their commuters actually have their commercial propaganda in front! Why not imagine that, one day, the contents of this area would be used to "target" the messages to be imposed to each and every passenger (on a skillfully located screen, for example, or by voice synthesis)? It is probably a little too early to pass the step, but we should remain on guard, because such practices would be (at the very least) shocking. More likely, the data that are currently recorded here might also be used for statistical purposes, such as traffic flow optimization, or as part of promotional strategies (to suggest a more appropriate scheme to a commuter when he comes to reload his pass?). Finally, let's remain vigilant with regard to any addition of data that would immediately follow a credit card reload, since with the help of EMV technology, the pass might permanently loose the anonymity it (hopefully) had when it was first issued.

Mifare and family
The "Mifare" technology (developed by Philips and now marketed by NXP Semiconductors) has long concerned over 80 % of RFID (13.56 MHz) applications, and was often hastily confused with the ISO14443 type A from which it derives. In fact, it adds a (proprietary) encryption layer for mutual authentication and encryption of the radio path, and therefore requires the presence of a specific secure component in each and every Mifare enabled reader. Despite a strict licensing policy, at least a fairly accurate chinese imitation (FUDAN) managed to enter the market. As far as public transportation is concerned, it is essentially Mifare Ultra Light and Mifare Classic that are used on the field. In the trash too, because Mifare Ultra Light paper-based tickets are sufficiently inexpensive to be made disposable (single trip). In fact, they cost the transport operator (and ultimately the passenger!) a significant part of the ticket price, but induce huge savings on operation and maintenance costs. Overall, it seems that the results are positive, as in the case of contactless Orly Val "C.ticket" disposable paper tickets. Ultimately, they should be used for all single-trip tickets in greater Paris.
In contrast to Calypso or Navigo passes that are true asynchronous smart cards (ie microprocessor based cards), the Mifare Classic and Mifare Ultra Light cards fall into the category of (moderately secure) synchronous memory cards. Consequently, they do not understand ISO7816 commands directly, but most readers are able to interact with them by accepting pseudo-APDUs (often easier to handle than native "micro-instructions"), and can even issue an ISO7816 compliant ATR (answer to reset). The main benefit is that, should the reader be PC/SC compatible (like the ACR122), it is possible to use the (free!) BasicCard software kit to explore also Mifare cards, without the need of a complete SDK, which is much more expensive that the "naked" reader! So, let's experiment this idea with Mifare Ultra Light "tags":

#Include CARDUTIL.DEF
#Include COMMERR.DEF
ComPort=101

Declare Command &HFF &HB0 ULIGHT(S$)

CLS:Print"ULIGHT (c)2008 Patrick GUEULLE"
Call WaitForCard
ResetCard (P$) : Call CheckSW1SW2
Print:Print
Print"ATR (Hist.): ";
FOR F=1 TO Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print:Print

T$=Mid$(P$,10,2)
IF T$<>Chr$(&H00)+Chr$(&H03) Then Goto OTHER

Print "Mifare Ultralight found! ":Print

P$=""
Call ULIGHT(P1P2=&H0000,P$,Le=16):Call CheckSW1SW2
H$=""
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
H$=H$+M$+" "
NEXT F
Print"UID: ";Left$(H$,26)
Print"Internal byte: ";Mid$(H$,28,2)
Print"LOCKS: ";Mid$(H$,31,5);
If Mid$(H$,31,5)="00 00" Then Print " (No lock is activated!)";
If Mid$(H$,31,5)="FF FF" Then Print " (All the locks are activated)";
Print
Print"OTP area: ";Right$(H$,12)
Print:Print"User zone:"
Print

P$=""
Call ULIGHT(P1P2=&H0004,P$,Le=16):Call CheckSW1SW2
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

P$=""
Call ULIGHT(P1P2=&H0008,P$,Le=16):Call CheckSW1SW2
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

P$=""
Call ULIGHT(P1P2=&H000C,P$,Le=16):Call CheckSW1SW2
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

OTHER:
IF T$=Chr$(&H00)+Chr$(&H01) Then Print"MIFARE 1K found"
IF T$=Chr$(&H00)+Chr$(&H02) Then Print"MIFARE 4K found"
IF T$=Chr$(&H00)+Chr$(&H26) Then Print"MIFARE Mini found"
IF T$=Chr$(&HF0)+Chr$(&H04) Then Print"TOPAZ or JEWEL found"
IF T$=Chr$(&HF0)+Chr$(&H11) Then Print"FELICA 212K found"
IF T$=Chr$(&HF0)+Chr$(&H12) Then Print"FELICA 424K found"
IF Left$(T$,1)=Chr$(&HFF) Then Print"Unknown 13.56 MHz tag"

Print:Print:Call WaitForNoCard

Specifically written for the ACR122, this short program (ULIGHT.BAS) can read the full memory space of any Mifare Ultra Light. Any memory "page" of this device can be permanently write-protected (by means of the so-called LOCKS bits), but never read-protected. Should another kind of RFID tag be placed onto the reader, the software would try to identify it (by decoding the reader's answer), so that an appropriate program could be used instead. Let's consider a disposable ticket from the Moscow tube: the answer to reset (ATR) that our program will display is not issued by the ticket, but built by the ACR122, mainly for PC/SC compatibility puposes. Therefore, its contents is not of tremendous interest, but may nevertheless be studied, with some help from the ACR122 Reference Manual. Just note, among its historical characters, the RID (registered identifier) of the PC/SC Workgroup.

ATR (Hist.): 80 4F 0C A0 00 00 03 06 03 00 03 00 00 00 00

The first really interesting field is the UID, ie the unique identifier of the card. A bit longer than the UID of a Calypso pass, it is used again to individually address the Mifare chip, should several devices be simultaneously present in the RF field of the reader. This process uses a technique known as "anti-collision", which is widely documented in the literature, but completely transparent to us, as fully managed by the reader. In the case of two tickets (purchased and used at about the same time), we can see that the results are quite different.

04 87 B8 B3 C1 2B 25 80 4F
04 30 48 F4 69 7E 23 80 B4

The next three fields are, by contrast, always the same from a (used) ticket to another:

Internal Byte: 48
LOCKS: F0 FF
OTP area: FF FF FF FC

The "Internal Byte" is set by the manufacturer, while the next six bytes were written by the issuer of the ticket (ie the transport operator), when issued, and/or when used. Each bit of both LOCKS bytes determines whether an area is write-protected (1) or not (0). The case of the OTP area is especially interesting, as one can write (change from 0 to 1) any of its bit irreversibly (no way to change back to 0). Obviously, all LOCKS bits are of the OTP type themselves. It appears that almost nothing can be changed in a used Moscow tube ticket (this is desirable to reduce the risk of fraud), but there are quite different situations elsewhere. In Venice, for example, the "Oviesse" pass, although based on a (normally) disposable technology, is indeed reloadable. Its LOCKS bytes are 00 00 (no active lock!), while the OTP (13 7E 00 00 in every used pass that we have reviewed) has still several bits that may be changed. It is in the "user area" that we will obviously find the bulk of potentially "sensitive" data, most likely coming, at least partially, from a cryptographic calculation. In our case of tickets for the Moscow tube, a redundancy feature seems to be implemented (the last two lines are identical, and by the way, somewhat similar from a ticket to another):

First ticket:

41 87 80 EA 5D 2B 88 17 D8 00 00 00 00 00 00 00
17 D4 05 00 00 00 05 4D 39 5A 74 ED 00 00 00 00
17 D4 05 00 00 00 05 4D 39 5A 74 ED 00 00 00 00

Second ticket:

41 87 80 CF CB A4 68 17 D8 00 00 00 00 00 00 00
17 D4 05 00 00 00 03 7D 14 05 40 17 00 00 00 00
17 D4 05 00 00 00 03 7D 14 05 40 17 00 00 00 00

The case of the Venetian pass is more interesting, since the entire "user area" can be freely modified, as many times as you want. This might seem unwise in terms of security, unless a strong cryptographic mechanism would exploit the uniqueness of the UID to authenticate the read-free / write-free data. Maybe an example that other operators should carefully study? Anyway, this feature justifies the development of a program (WRULIGHT.BAS) to write into Mifare Ultra Light (which can also be purchased, blank except for the UID, through various retailers). Of course, prior to using it to tamper with an existing pass, one should carefully read and record its entire contents, in order to restore it (where possible) back to its initial state.

#Include CARDUTIL.DEF
#Include COMMERR.DEF
ComPort=101
Public RX$ As String*4
Declare Command &HFF &HB0 ULIGHT(S$)
Declare Command &HFF &HD6 WRPAGE(S$)
CLS:Print"WRULIGHT (c)2008 Patrick GUEULLE"

Call WaitForCard()
ResetCard (P$):Call CheckSW1SW2()
Print:Print"ATR (Hist.): ";
FOR F=1 TO Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F

Print:Print

P$=""
Call ULIGHT(P1P2=&H0008,P$,Le=16):Call CheckSW1SW2:RX$=P$
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

P$=String$(4,&HAB)
Call WRPAGE(P1P2=&H0008,P$,Disable Le)

P$=""
Call ULIGHT(P1P2=&H0008,P$,Le=16)
If SW1SW2=&H6300 Then Print "Failed!"
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

Call WRPAGE(P1P2=&H0008,RX$,Disable Le)

P$=""
Call ULIGHT(P1P2=&H0008,P$,Le=16)
FOR F=1 To Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print:Print

Call WaitForNoCard

This is exactly what our program does: it just writes the four ABABABABh bytes into a "page" (0008h), the contents of which having previously been saved in the RX$ string. Immediately after checking the success of the writing process, it restores the original state, thus allowing one to play, taking only very little risk, with a wide variety of samples. Of course, this scenario is purely experimental, and would require further development, should a truly practical application be devised!

Mifare Classic: Beware!
With much more memory than the 64 bytes of a Mifare Ultra Light, Mifare Classic is available in 1K (16 sectors each containing 16 blocks of 4 bytes) and 4K versions. Such a partitioned organization is a good thing for multi-applications cards, thanks to diversified cryptographic keys. Many sensitive applications (including access control of to strategic premises) were built from these widely available and popular components, but their security is now being undermined. By tampering at the lowest hardware and software levels, Dutch academics have indeed managed to compromise the secrecy of the encryption system (CRYPTO1) between the card and reader, and thus to read or modify memory areas for which they did not have the correct key (just run a search on "Mifare" and "Hack" with your favorite Internet search engine for more information). This has threatened the huge public transport system of London, which is based on Mifare 1K technology (Oyster). Although it is commonly accepted that riding for free by tube is less serious than entering a government building without permission, the risk of large scale fraud could not be neglected.
To assess the vulnerability of a particular application based on Mifare Classic, one should check whether the developer felt himself happy with just the embedded cryptography of the chips, or has set up one or more additional layers. In the first case, everything might collapse, should illegal access be obtained to normally read-protected data. In the second, even if genuine pass would be cloned by fraudsters (blank Mifare Classic are readily available from specialist retailers), the uniqueness of each UID would possibly prevent them from being accepted as valid. The problem is that the usefulness of this unique and unalterable (but what about counterfeited products or even emulators?) is often underestimated... Fighting a wave of fraud made possible by a poor design may require to put online, systems originally designed to operate in a local authentication mode: the negation of the very concept of (contact or contactless) smart cards, but this has happened and will happen again!

photo Pass CARTES 2005

Apart from making use of the abovementioned vulnerability (which is not exactly straightforward!), exploring transportation passes based on this technology can only be achieved within certain limits. We did establish that in the transportation pass of Warsaw, for example, some sectors are read-protected by secret keys. In contrast, visitor badges for the CARTES exhibition (which are also Mifare 1K) have always been issued with the default (so-called "transport") keys. This means that anyone could read their entire contents (not a major threat!) but also delete all or part for reuse (which might be worth doing). Hence the idea to develop software tools allowing us to manipulate as freely as possible, again with our faithful BasicCard kit (even if it was never designed for this purpose)!

#Include CARDUTIL.DEF
#Include COMMERR.DEF
ComPort=101
Declare Command &HFF &H82 LDK(S$)
Declare Command &HFF &H86 AUT(S$)
Declare Command &HFF &HB0 RD(S$)
Declare Command &HFF &HCA UID(S$)

CLS:Print"MIFHEX (c)2008 Patrick GUEULLE"
Call WaitForCard()
ResetCard (P$)
Print:Print"ATR (Hist.): ";
FOR F=1 TO Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print:Print

T$=Mid$(P$,10,2)
IF T$<>Chr$(&H00)+Chr$(&H01) Then Goto OTHER
Print "Mifare 1K found! ":Print

S$="":Call UID(S$,Le=4):Call CheckSW1SW2
Print "UID: ";
For F=1 To 4
K$=Mid$(S$,F,1)
K=Asc(K$)
Print Hex$(K);" ";
Next F
Print:Print:Print"Space bar: Next sector, Esc: Quit":Print

S$=Chr$(&HA0)+Chr$(&HA1)+Chr$(&HA2)+Chr$(&HA3)+Chr$(&HA4)+Chr$(&HA5)
S$=Chr$(&HB0)+Chr$(&HB1)+Chr$(&HB2)+Chr$(&HB3)+Chr$(&HB4)+Chr$(&HB5)
S$=Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)
Call LDK(P1P2=&H0000,S$,Disable Le):Call CheckSW1SW2

For SECT=0 To 15
For BLOCK=0 To 3

S$=Chr$(&H01)+Chr$(&H00)+Chr$(SECT*4)+Chr$(&H60)+Chr$(&H00)
Call AUT(P1P2=&H0000,S$,Disable Le)
If SW1SW2=&H6300 Then Print "Sector ";SECT;": wrong key?";:Goto Jump
If SW1SW2=26514 Then Print "No card found!":Goto Quit

S$="":Call RD(P1P2=SECT*4+BLOCK,S$,Le=16)
FOR F=1 TO Len(S$)
M=ASC(MID$(S$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

Next BLOCK
Jump:
K$=Inkey$
If K$=Chr$(27) Then Goto Quit
If K$<>Chr$(32) Then Goto Jump
Print:Next SECT

OTHER:
IF T$=Chr$(&H00)+Chr$(&H03) Then Print"MIFARE Ultralight found"
IF T$=Chr$(&H00)+Chr$(&H02) Then Print"MIFARE 4K found"
IF T$=Chr$(&H00)+Chr$(&H26) Then Print"MIFARE Mini found"
IF T$=Chr$(&HF0)+Chr$(&H04) Then Print"TOPAZ ou JEWEL found"
IF T$=Chr$(&HF0)+Chr$(&H11) Then Print"FELICA 212K found"
IF T$=Chr$(&HF0)+Chr$(&H12) Then Print"FELICA 424K found"
IF Left$(T$,1)=Chr$(&HFF) Then Print"Unknown 13.56 MHz tag"

Quit:
Print:Print:Call WaitForNoCard

The first program (MIFHEX.BAS) can read the entire memory of a Mifare 1K whose default keys have remained unchanged. As everybody should know, the normal value is FF FF FF FF FF FF (default key), but one can also try A0 A1 A2 A3 A4 A5 (key A) or B0 B1 B2 B3 B4 B5 (key B). These three values are pre-programmed in our source code, so one can simply erase the unnecessary lines before compiling it, or modify their order, since only the last one is taken into account. Chronologically, we begin by loading the key into the reader (an ACR122 installed as No. 1 PC/SC reader, ie ComPort=101), by means of an LDK (Load Key) command. The next thing to do is to authenticate with this key (login) each time you access a new sector (AUT command). Of course, additional LDK commands might be inserted just before each AUT command, so as to use different keys for each sector. Provided that the verification of the key is successful, several read commands (RD) will be used to read blocks in the "opened" sector, pressing the space bar to move to the next one. A Mifare 1K contains 4 in each of the 16 sectors that are a Mifare 1K, and a Mifare 4K contains four times more data. This is significantly higher than in a Navigo pass, allowing TFL (Transport for London) to save a larger "journal", but in a potentially less safe carrier.

Some applications (access to the CARTES exhibition conference rooms, for example) essentially record alphanumeric data into the Mifare, so let's see how to modify our program (MIFASC.BAS), to make it decode the bytes as ASCII strings:

#Include CARDUTIL.DEF
#Include COMMERR.DEF
ComPort=101
Declare Command &HFF &H82 LDK(S$)
Declare Command &HFF &H86 AUT(S$)
Declare Command &HFF &HB0 RD(S$)
Declare Command &HFF &HCA UID(S$)
CLS:Print "MIFASC (c)2008 Patrick GUEULLE"
Call WaitForCard()
ResetCard (P$)
Print:Print"ATR (Hist.): ";
FOR F=1 TO Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F

Print:Print
ResetCard (P$)
S$="":Call UID(S$,Le=4):Call CheckSW1SW2
Print "UID: ";
For F=1 To 4
K$=Mid$(S$,F,1)
K=Asc(K$)
Print Hex$(K);" ";
Next F
Print:Print

S$=Chr$(&HA0)+Chr$(&HA1)+Chr$(&HA2)+Chr$(&HA3)+Chr$(&HA4)+Chr$(&HA5)
S$=Chr$(&HB0)+Chr$(&HB1)+Chr$(&HB2)+Chr$(&HB3)+Chr$(&HB4)+Chr$(&HB5)
S$=Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)
Call LDK(P1P2=&H0000,S$,Disable Le):Call CheckSW1SW2

For SECT=0 To 15
For BLOCK=0 To 2

S$=Chr$(&H01)+Chr$(&H00)+Chr$(SECT*4)+Chr$(&H60)+Chr$(&H00)
Call AUT(P1P2=&H0000,S$,Disable Le)
If SW1SW2=&H6300 Then Print "Secteur ";SECT;": Wrong key?":Goto Jump
If SW1SW2=26514 Then Print "No card found!":Goto Quit

S$="":Call RD(P1P2=SECT*4+BLOCK,S$,Le=&H10)
Print S$

Next BLOCK
Jump:
Next SECT
T$=Mid$(P$,10,2)
Print:Print:Call WaitForNoCard

Now, let's see (MIFWR.BAS) how to write into a Mifare 1K, again with our ACR122 associated with the BasicCard software kit. Having no practical application in mind, we will just record 16 ABh bytes in a block (No. 1 of sector 15) which have been previously stored in the RX$ string. After checking the success of the operation (and thus the validity of the key!), the initial state is restored (but do not withdraw the Mifare card in a meantime...). Please note that the first block (No. 0) of each sector contains system bytes, which should not be altered without knowing exactly what we are doing (carefully read the NXP data literature, which is publicly available)!

#Include CARDUTIL.DEF
#Include COMMERR.DEF
ComPort=101
Declare Command &HFF &H82 LDK(S$)
Declare Command &HFF &H86 AUT(S$)
Declare Command &HFF &HB0 RD(S$)
Declare Command &HFF &HCA UID(S$)
Declare Command &HFF &HD6 WR(S$)
Public RX$ As String*16

CLS:Print"MIFWR (c)2008 Patrick GUEULLE"
Call WaitForCard()
ResetCard (P$)
Print:Print"ATR (Hist.): ";
FOR F=1 TO Len(P$)
M=ASC(MID$(P$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F

Print:Print
S$="":Call UID(S$,Le=4):Call CheckSW1SW2
Print "UID: ";
For F=1 To 4
K$=Mid$(S$,F,1)
K=Asc(K$)
Print Hex$(K);" ";
Next F
Print:Print

S$=Chr$(&HA0)+Chr$(&HA1)+Chr$(&HA2)+Chr$(&HA3)+Chr$(&HA4)+Chr$(&HA5)
S$=Chr$(&HB0)+Chr$(&HB1)+Chr$(&HB2)+Chr$(&HB3)+Chr$(&HB4)+Chr$(&HB5)
S$=Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)+Chr$(&HFF)
Call LDK(P1P2=&H0000,S$,Disable Le):Call CheckSW1SW2

S$=Chr$(&H01)+Chr$(&H00)+Chr$(15*4)+Chr$(&H60)+Chr$(&H00)
Call AUT(P1P2=&H0000,S$,Disable Le):Call CheckSW1SW2

S$="":Call RD(P1P2=15*4+1,S$,Le=16):RX$=S$
FOR F=1 TO Len(S$)
M=ASC(MID$(S$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

S$=String$(16,&HAB)
Call WR(P1P2=15*4+1,S$,Disable Le):Call CheckSW1SW2

S$="":Call RD(P1P2=15*4+1,S$,Le=16)
FOR F=1 TO Len(S$)
M=ASC(MID$(S$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

Call WR(P1P2=15*4+1,RX$,Disable Le):Call CheckSW1SW2

S$="":Call RD(P1P2=15*4+1,S$,Le=16)
FOR F=1 TO Len(S$)
M=ASC(MID$(S$,F,1))
M$=HEX$(M):IF Len(M$)=1 Then M$="0"+M$
PRINT M$;" ";
NEXT F
Print

Print:Print:Call WaitForNoCard


Version française

Patrick Gueulle

Tous les ouvrages de l'auteur





[homepage] [RSS] [archives]
[contact & legal & cookies] © ACBM