Comment nous avons perdu 230 euros chez CJ Affiliate (Conversant)

vers Virus Info


[accueil]  [menu]  [suivez-nous !]  [chercher]


2009-03-10 00:00

Les secrets des Pass de transports en commun


English version

Paris, Londres, Moscou, Amsterdam, Varsovie, Venise...


Le 31 janvier 2009, la Carte Orange et son coupon magnétique ont disparu du paysage francilien, cédant définitivement la place au pass Navigo sans contact. Couronnement de plus de dix ans d'efforts de la RATP, de la SNCF et d'Innovatron, cet événement est pourtant bien en retard par rapport à ce qui s'est déjà fait ailleurs... Le moment est donc enfin venu de pénétrer ces cartes à puce pas comme les autres, à la découverte de tous leurs petits mystères que nous brûlions d'éclaircir ! Peuvent-elles vraiment nous suivre à la trace ? Nous allons en avoir le cœur net...

A vrai dire, la « télébillettique » est une réalité du monde des transports en commun depuis déjà plusieurs années : si Londres a fait figure de pionnier avec le déploiement précoce d'Oyster (technologie Mifare), c'est de France que tout est parti avec le projet Calypso. A l'origine, une technologie sans contact développée par Innovatron a su convaincre la RATP et la SNCF, rejoints dans les années 1990 par des opérateurs de transport du monde entier. Dès 2003, l'occasion nous était donnée d'expérimenter le produit, le badge « congressiste » du salon CARTES incorporant, précisément, un pass Navigo offrant l'accès gratuit aux transports en commun. A l'époque, un coupon magnétique accompagnait encore la carte à double interface (avec et sans contacts), car peu de stations étaient équipées en RFID. Cette bonne initiative, écologiquement correcte, a fait long feu en 2008, soit un an après le fort discret lancement du pass Navigo Découverte (réputé anonyme) en septembre 2007. Plus besoin, donc, de résider en Ile-de-France pour se procurer un pass Navigo, à condition toutefois de payer son « prix coûtant » de 5 € !

photo 4 Pass

Est-ce donc le moment de s'équiper d'un lecteur de cartes à puce sans contact, tel que l'excellent ACR122 d'ACS ? Assurément, mais pas pour « bricoler » les pass Navigo ! Ceux-ci n'en finissent pas, en effet, de s'affranchir du vieux protocole de communication Innovatron, franco-français et différent de l'ISO14443 Type B dont il est en quelque sorte l'ancêtre. Qu'à cela ne tienne ! Les Navigo étant équipés, en plus de leur antenne, d'une puce à contacts ISO7816, on arrive à procéder aux mêmes manipulations avec n'importe quel lecteur PC/SC et le désormais habituel kit BasicCard. Providentiellement compatible avec ce dernier, l'ACR122 servira plutôt à explorer (non sans surprises !) les tickets jetables ou non, basés sur la technologie Mifare (Londres, Varsovie, Moscou, Venise, Amsterdam et d'innombrables autres villes de par le monde). Bien plus, il est d'ores et déjà prêt pour la NFC (Near Field Communication) qui n'attend plus, pour envahir notre quotidien, que la généralisation des téléphones portables compatibles : un futur grand dossier sur lequel nous travaillons déjà d'arrache-pied...

Des spécifications confidentielles
Contrairement à ce qui se pratique dans les domaines de la téléphonie mobile (cartes SIM et USIM) ou de la monétique (cartes bancaires EMV), les spécifications des applications télébillettiques sont en grande partie confidentielles. Il faut donc montrer patte blanche pour y accéder (notamment à des fins d'interopérabilité), privilège qui nous a été aimablement accordé. Pas question, par conséquent, de trahir la confiance qui nous est ainsi témoignée, en reproduisant ici ou là des documents classifiés, même si leur étude serait plutôt de nature à décourager d'éventuels fraudeurs qu'à leur donner des idées. Par contre, nous estimons être en droit de fournir à nos lecteurs des logiciels leur permettant de prendre connaissance du contenu des zones à lecture libre de leurs pass, afin qu'ils puissent déterminer eux-mêmes s'ils doivent ou non se sentir « pistés ».
Compte tenu du très haut degré de standardisation des pass Calypso, les méthodes qui vont être présentées dans le cas du Navigo pourront être extrapolées, avec peu ou pas de modifications, à d'autres titres de transport « dématérialisés » (par exemple le Weneo Pass de Neowave, vedette du salon CARTES 2008, déjà en cours d'expérimentation sur certains réseaux ferroviaires). Schématiquement, la mémoire d'un pass Calypso (et donc d'un Navigo) est divisée en un petit nombre de zones dont le rôle, parfaitement défini, est clairement détaillé dans les fiches commerciales (publiques) des différents fabricants (par exemple ASK avec sa famille TanGO) ou des fondeurs des puces dont ils se servent (par exemple STMicroelectronics) :
- des éléments d'identification du badge et/ou du titulaire ;
- des informations sur le titulaire ;
- un journal de transport ;
- des contrats ;
- des compteurs ;
- une zone événements spéciaux ;
- une zone comportement et fidélité.
Bien entendu, de puissants mécanismes cryptographiques (tenus secrets !) protègent l'écriture dans ces zones et assurent l'authentification mutuelle de la carte et du terminal. Ah, si toutes les applications « carte » étaient bâties avec autant de rigueur...

photo Pass CARTES 2003

Parallèlement à cette application télébillettique, certaines versions dites « multi-applications » peuvent incorporer un porte-monnaie électronique (PME) et/ou une application multi-usage (MPP), telle que l'accès aux conférences du salon CARTES. Nécessaires et suffisantes pour gérer (nominativement ou anonymement) l'utilisation de transports en commun de type métro, RER, tramway ou autobus, toutes ces entités ne sont pas forcément mises à contribution pour un usage « grandes lignes ». C'est ainsi que l'utilisation d'un pass Navigo pour prendre le TGV Thalys repose uniquement sur la lecture de son numéro de série, la fonctionnalité sécuritaire étant assurée (tout comme la réservation en ligne) par un système informatique central. Même chose pour la location de vélos (Vélib), le pass Navigo ne servant que de moyen d'identification commode par rapport à un contrat souscrit... nominativement. Les fonctionnalités cryptographiques du pass ne sont alors nullement mises à contribution (ce qui est fort dommage...), et l'on pourrait tout aussi bien faire la même chose avec un badge de pointeuse ! Le nombre de contrats est cependant largement suffisant pour un possible usage international : à quand l'acceptation du pass Navigo dans les tramways de Bruxelles, ou de la carte belge Mobib dans le métro parisien ?

Le pass Navigo à la loupe
Une fois de plus, un très simple code source ZCBasic suffira pour procéder à une lecture quasiment exhaustive, à l'aide d'un simple lecteur PC/SC à contacts (par exemple TeoByXiring). Mais la beauté de la chose, c'est que grâce à une commande supplémentaire de sélection d'application (AID 1TIC.ICA), le même programme BILLET.BAS pourra fonctionner, le moment venu, en mode sans contact avec un ACR122 ou tout autre lecteur RFID/NFC opérant en mode PC/SC (leur démocratisation était, à nos yeux, l'une des grandes nouvelles du salon CARTES 2008). Nous pouvons d'ailleurs d'ores et déjà révéler que cela fonctionne plutôt bien avec le Weneo « spécial Presse » qui nous a été remis, en avant-première, lors dudit salon...

#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"TELEBILLETTIQUE (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 "Informations titulaire (ENV) : ":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"--- RETOUR A LA LIGNE pour voir le journal ---"
Input Z$:CLS
Print "Journal de transport : ":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"--- RETOUR A LA LIGNE pour voir les contrats ---"
Input Z$:CLS
Print "Contrats 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"Contrats 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"--- RETOUR A LA LIGNE pour voir les compteurs ---"
Input Z$:CLS
Print"Compteurs :":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"--- RETOUR A LA LIGNE pour voir le reste ---"
Input Z$:CLS
Print"Evenements speciaux :":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"Comportement et fidelite :":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

Selon les badges (existants ou futurs, jetables ou non) qu'il s'agira d'explorer, d'autres AID pourront être essayés : 3MTR.ICA, 1TIC.ICAn (avec n allant de 1 à 4), 2MPP.ICA, F0424D532E455469636B6574h (BMS.ETicket), OETP.ICA, etc. Cela pourra nécessiter, toutefois, de modifier aussi les identifiants de tout ou partie des fichiers à lire, ce qui nous entraînerait bien trop loin si nous tentions de détailler. Pour l'heure, remarquons en tout premier lieu que seul un fichier dit « identification du titulaire » ne peut être lu sans la présentation d'un code PIN... que nous n'avons pas. C'est dommage, certes, mais dans le cas particulier d'un pass Navigo Découverte payé en espèces, il ne peut en aucun cas (du moins à l'origine) contenir des données indiscrètes. Tout le reste est en lecture libre, mais « défini par l'opérateur de transport » (sic.) ! C'est dire qu'il va falloir faire preuve de perspicacité pour interpréter les résultats de notre lecture, la règle du jeu étant de ne se référer à aucune spécification confidentielle. Prenons l'exemple du fichier « Informations sur le badge », dont les 29 octets pourraient se présenter comme suit :

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

En rouge, on retrouve 4 octets qui figurent également dans l'ATR (réponse au reset) et qui correspondent, nous l'avons vérifié, à l'identifiant unique du pass (celui qui sert à l'adresser lors d'une communication sans contact). En vert, on reconnaît le même code pays (normalisé) que dans les cartes bancaires : 0250 pour la France. A part cela, beaucoup de 00 (ou de FF selon l'année) dans ces Navigo émis lors du salon CARTES... Comparons maintenant la zone « Informations sur le titulaire » entre ce même pass de CARTES 2006, et un Navigo Découverte émis début 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

Seulement six octets diffèrent, à trois ans d'intervalle, entre ces deux pass dont l'un au moins est anonyme : très insuffisant pour coder des détails par trop personnels, mais rien n'interdit d'exercer une surveillance périodique si on a des doutes, puisqu'il reste pas mal de place libre...

Sujet sensible s'il en est, le fameux « journal de transport » dans lequel s'enregistrent les faits et gestes du voyageur. Mais il faut relativiser ! Toutes les informations publiquement accessibles (et vérifiables sur pièces) concordent : ce « mouchard » est limité à trois enregistrements de 29 octets, soit le strict minimum permettant à un contrôleur de s'assurer que tout est en règle. En pratique, ce sont donc les trois dernières présentations du pass devant un validateur qui sont ainsi enregistrées. A Londres, haut-lieu de la vidéosurveillance, un pass Oyster remonterait bien plus loin dans le temps : jusqu'à 25 événements, ce qui est infiniment plus déplaisant... Le point intéressant est que ces « compostages » sont horodatés, tout comme sur un ticket papier. Examinons ainsi les trois entrées du journal de transport de ce fameux pass Navigo du salon CARTES 2006, qui a servi en tout et pour tout à effectuer un trajet en RER (SNCF puis RATP) de Villepinte (Parc des expositions) à St-Germain-en-Laye, le 9 novembre en fin d'après-midi :

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

Les quatre premiers octets font penser à un « timestamp », et étaient invariablement à 11 1D 68 10 sur tous les pass jamais utilisés qu'il nous a été donné d'examiner. Si nous divisons par 4 et convertissons en décimal les deux entiers hexa 38 3E 17 90 et 38 3D F4 10, nous obtenons respectivement 235898340 et 235896068 secondes, à partir d'un instant initial que l'opérateur de transport ne souhaite apparemment pas révéler. Qu'importe ! La différence entre ces deux valeurs est de 2272 secondes, soit sensiblement 38 minutes, ce qui correspond à un temps de parcours vraisemblable dans le cas (vécu !) d'une correspondance quasiment immédiate à Châtelet-Les Halles. Il semblerait donc que soient ainsi enregistrés les instants d'entrée sur le réseau et de sortie de celui-ci, les plus récents événements venant très logiquement écraser les plus anciens. Les quelques octets qui suivent identifient fort probablement les stations où le pass a été présenté, selon un codage lui aussi tenu secret. Bien des choses risquent toutefois d'apparaître au grand jour si on se donne la peine de consulter ce journal trajet après trajet, surtout si on fréquente souvent les mêmes stations. Mais la principale conclusion qu'il convient de tirer de ces premières investigations est qu'il n'y a (ici) aucunement matière à s'inquiéter pour notre vie privée, du moins tant qu'on ne laisse pas n'importe qui accéder à ces données !

Passons maintenant à la zone des contrats, qui se compose encore et toujours d'enregistrements de 29 octets. Dans le cas du pass CARTES 2006, l'abonnement « congrès » de trois jours (du 18 au 20 novembre), valable pour les zones 1 à 4, est visiblement représenté par une suite de 23 octets, tout le reste de la zone étant rempli de 00. Il est éminemment probable que ces données soient cryptées, mais rien n'interdit de chercher à leur trouver une signification (souvenons-nous des résultats inespérés que cela a donné avec la carte Vitale !).

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

Le Navigo Découverte, n'ayant pas encore fait l'objet d'un quelconque chargement, apparaît pour sa part « pré-formaté » mais bien évidemment, tout comme notre Weneo échantillon, vierge de tout contrat :

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

Tel est également le cas des zones qui suivent, sauf pour l'enregistrement « comportement et fidélité » qui, dans notre Navigo de CARTES 2006 (utilisé juste une fois), révèle quatre mystérieux octets :

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

Dans tous nos Navigo neufs ou inutilisés, par contre, cette zone est intégralement vierge :

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

C'est dans ces parages que l'on aurait le plus de chances de voir arriver, à notre humble avis, des données potentiellement dérangeantes. Les opérateurs de transport public commencent en effet à vendre, à des annonceurs publicitaires, le temps pendant lequel leurs clients ont réellement leur propagande commerciale sous les yeux ! De là à imaginer que le contenu de cette zone pourrait un jour être exploité pour « cibler » la publicité à infliger à chaque voyageur (sur un écran habilement disposé, par exemple, ou encore par une voix de synthèse), il n'y a qu'un pas qu'il est sans doute un peu tôt pour franchir. Mais il convient de rester sur ses gardes, car de telles pratiques seraient pour le moins choquantes. Plus vraisemblablement, les données qui y sont actuellement enregistrées pourraient aussi servir à des fins statistiques, en vue d'optimiser les flux de trafic, ou bien dans le cadre d'opérations promotionnelles (suggérer une formule tarifaire plus appropriée à un client venant recharger son pass). Enfin, restons vigilants quant à toute adjonction de données qui suivrait immédiatement un rechargement par carte bancaire : avec la complicité de la technologie EMV, la manoeuvre pourrait très bien faire perdre définitivement au pass le caractère anonyme qu'il pouvait avoir lors de son émission.

Mifare et compagnie
La technologie Mifare (d'origine Philips et désormais commercialisée par NXP Semiconductors) a longtemps concerné plus de 80 % des applications RFID (13,56 MHz), et a été souvent confondue un peu vite avec l'ISO14443 Type A dont elle dérive. En réalité, elle y ajoute une couche cryptographique (propriétaire) d'authentification mutuelle et de chiffrement des communications radio, et nécessite donc la présence d'un composant sécuritaire spécifique dans chaque lecteur. Malgré une politique de licenses très stricte, au moins une imitation chinoise assez fidèle (FUDAN) a réussi à s'introduire sur le marché. Dans le domaine des transports en commun, ce sont essentiellement les gammes Mifare Ultra Light et Mifare Classic que l'on rencontre sur le terrain. Dans les poubelles aussi, car les tickets « papier » Mifare Ultra Light sont suffisamment peu coûteux pour être jetables (trajet unique). Dans les faits, ils coûtent à l'opérateur de transport (et finalement au voyageur !) une part assez significative du prix du billet, mais induisent de fortes économies sur l'exploitation et la maintenance. Globalement, il paraît donc que le bilan serait positif, tout comme dans le cas des C.ticket sans contact et jetables d'Orly-Val, appelés à se généraliser (à terme) à tous les trajets ponctuels en Ile-de-France.
Par opposition aux pass Navigo ou Calypso qui peuvent être assimilés à des cartes à puce asynchrones (autrement dit à microprocesseur), les Mifare Classic et a fortiori Ultra Light se classent dans la catégorie des cartes à mémoire (synchrones) moyennement sécurisées. Ils ne comprennent donc pas directement les commandes ISO7816, mais la plupart des lecteurs capables de dialoguer avec eux acceptent, eux, des pseudo-APDU on ne peut plus faciles à manier, et reconstituent même une réponse au reset (ATR) plausible. L'immense intérêt de la chose, c'est que pour peu que le lecteur en question soit compatible PC/SC (et c'est le cas de l'ACR122), on pourra se servir du kit logiciel BasicCard (gratuit !) pour explorer aussi les cartes Mifare, et faire ainsi l'économie d'un SDK bien plus coûteux que le lecteur « nu » ! Voyons donc un peu ce que cela donne dans le cas des Mifare Ultra Light :

#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 reconnu ! ":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"Octet interne : ";Mid$(H$,28,2)
Print"LOCKS : ";Mid$(H$,31,5);
If Mid$(H$,31,5)="00 00" Then Print " (Aucun verrou actif !)";
If Mid$(H$,31,5)="FF FF" Then Print " (Tous les verrous sont actifs)";
Print
Print"Zone OTP : ";Right$(H$,12)
Print:Print"Zone utilisateur :"
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 reconnu"
IF T$=Chr$(&H00)+Chr$(&H02) Then Print"MIFARE 4K reconnu"
IF T$=Chr$(&H00)+Chr$(&H26) Then Print"MIFARE Mini reconnu"
IF T$=Chr$(&HF0)+Chr$(&H04) Then Print"TOPAZ ou JEWEL reconnu"
IF T$=Chr$(&HF0)+Chr$(&H11) Then Print"FELICA 212K reconnu"
IF T$=Chr$(&HF0)+Chr$(&H12) Then Print"FELICA 424K reconnu"
IF Left$(T$,1)=Chr$(&HFF) Then Print"Tag 13,56 MHz inconnu"

Print:Print:Call WaitForNoCard

Spécifiquement écrit pour l'ACR122, ce petit programme (ULIGHT.BAS) lit la totalité de l'espace mémoire de n'importe quel Mifare Ultra Light, dont les différentes zones ne peuvent être protégées qu'en écriture (par des verrous baptisés LOCKS), mais jamais en lecture. Si d'aventure un autre type de tag RFID devait lui être présenté, il s'efforcerait de l'identifier, afin qu'un logiciel approprié puisse lui être substitué. Prenons l'exemple d'un ticket de métro jetable de Moscou : la réponse au reset (ATR) qu'affiche notre programme n'est pas émise par lui, mais bien par le lecteur, essentiellement à des fins de compatibilité PC/SC. Son interprétation n'est donc pas d'un grand intérêt, mais peut néanmoins se faire à partir du manuel de référence de l'ACR122. Notons tout de même la présence, parmi ses caractères historiques, de l'identifiant (RID) du PC/SC Workgroup.

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

Le premier champ vraiment intéressant qui s'affiche est l'UID, autrement dit l'identifiant unique de la carte. Plus long que celui des pass Calypso, il sert là encore à adresser individuellement la puce Mifare même si plusieurs sont simultanément dans le champ radio du lecteur. Ce processus fait appel à une technique dite « anti-collision », largement documentée dans la littérature, mais totalement transparente pour nous, car entièrement gérée par le lecteur. Dans le cas de deux tickets achetés et utilisés à peu près à la même époque, on voit que les résultats obtenus sont franchement différents :

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

Les trois champs suivants sont, par contre, toujours identiques d'un ticket (usagé) à l'autre :

Octet interne : 48
LOCKS : F0 FF
Zone OTP : FF FF FF FC

L'octet interne est fixé par le fabricant, tandis que les six qui suivent ont été écrits par l'émetteur du ticket (autrement dit l'opérateur de transport), lors de son émission et/ou de son utilisation. Chaque bit des deux octets LOCKS détermine si une zone donnée est protégée (1) ou non (0) en écriture. Le cas de la zone OTP est un peu particulier, dans la mesure où quand on peut y écrire (mise à 1 de bits qui sont encore à zéro), c'est de façon irréversible (pas moyen de les remettre à 0). Notons d'ailleurs que les bits LOCKS sont évidemment eux-mêmes de type OTP. On comprend qu'on ne peut pratiquement plus rien modifier dans un ticket de métro moscovite utilisé (ce qui est d'ailleurs souhaitable pour limiter le risque de fraude), mais il n'en va pas partout ainsi. A Venise, par exemple, les pass Oviesse, bien que basés sur une technologie en principe jetable, sont en effet rechargeables. Leurs octets LOCKS sont donc à 00 00 (aucun verrou actif !), tandis que la zone OTP (13 7E 00 00 dans tous les pass que nous avons examinés) recèle encore de nombreux bits modifiables. C'est dans la zone utilisateur que se situe évidemment le gros des données « sensibles », très vraisemblablement issues, au moins partiellement, d'un calcul cryptographique. Dans le cas des tickets de métro de Moscou, un mécanisme de redondance saute immédiatement aux yeux (contenu identique des deux dernières lignes, d'ailleurs assez similaires d'un ticket à l'autre) :

Premier 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

Le cas des pass vénitiens est plus intéressant, dans la mesure où l'intégralité de la zone utilisateur peut être modifiée en toute liberté, autant de fois qu'on le souhaite. Cela peut paraître imprudent sur le plan de la sécurité, sauf si une solide cryptographie exploite intelligemment l'unicité de l'UID pour authentifier les données à lecture et écriture libres. Peut-être tenons nous-là un exemple que certains autres opérateurs feraient bien de méditer... Quoi qu'il en soit, cela justifie le développement d'un logiciel (WRULIGHT.BAS) permettant d'écrire dans des Mifare Ultra Light (que l'on peut d'ailleurs se procurer, vierges à l'exception de l'UID, dans le commerce). Naturellement, avant de s'en servir pour expérimenter sur un pass existant, on prendra soin de lire et noter intégralement son contenu, afin de pouvoir le restaurer (là où c'est possible) dans son état initial.

#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 "Echec de la modification !"
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

C'est très exactement ce que fait notre programme, qui se contente d'écrire les quatre octets ABABABABh dans une « page » (0008h) dont il a sauvegardé auparavant le contenu dans la variable RX$. Après vérification du succès de la modification, il rétablit l'état d'origine, ce qui permet d'opérer sans grand risque sur une grande variété de cobayes. Bien entendu, ce scénario purement expérimental serait à étoffer si une véritable application pratique devait être mise sur pied !

Mifare Classic : attention !
Dotés d'une capacité mémoire bien supérieure aux 64 octets du Mifare Ultra Light, les Mifare Classic se déclinent principalement en versions 1K (16 secteurs contenant chacun 4 blocs de 16 octets) et 4K. Cette organisation partitionnée se prête bien à un usage multi-applications, à base de clefs cryptographiques diversifiées. Beaucoup d'applications sensibles (y compris de contrôle d'accès à des enceintes stratégiques) ont été bâties à partir de ces composants très répandus, mais dont la sécurité est aujourd'hui mise à mal. En intervenant au plus bas niveau matériel et logiciel, des universitaires néerlandais ont en effet réussi à percer le secret du système de chiffrement (CRYPTO1) entre la carte et le lecteur, et du coup à lire ou modifier des zones de mémoire pour lesquelles ils ne disposaient pas de la bonne clef (faire une recherche sur « Mifare » et « Hack » dans votre moteur de recherche Internet favori pour en savoir plus). Cela a failli faire trembler sur ses bases l'énorme système de transport public londonien, basé sur des Mifare 1K (Oyster). Même s'il est communément admis qu'effectuer gratuitement un trajet en métro est moins grave que s'introduire subrepticement dans un bâtiment gouvernemental, le risque de systématisation de la fraude ne pouvait être négligé.
Pour évaluer la vulnérabilité de telle ou telle application basée sur Mifare Classic, il faut déterminer si le développeur s'est contenté de faire confiance à la cryptographie embarquée d'origine dans les puces, ou s'il a mis en place une ou plusieurs couches supplémentaires. Dans la première hypothèse, tout risque de s'écrouler dès lors que l'on peut prendre connaissance de données normalement protégées en lecture. Dans la seconde, même si de vrais pass devaient être clonés par des fraudeurs (puisque des Mifare Classic vierges sont facilement disponibles au détail), l'unicité de chaque UID pourrait suffire à déjouer leurs efforts. L'ennui, c'est que l'utilité de cet identifiant unique et inaltérable (mais l'est-il réellement sur un produit de contrefaçon ou un émulateur ?) est bien souvent sous-estimée... Reprendre l'initiative face à une vague de fraude rendue possible par des négligences de conception peut obliger à faire basculer « en ligne » des systèmes conçus à l'origine pour fonctionner en authentification locale : la négation même de tout l'intérêt des cartes à puce, avec ou sans contact, mais cela s'est déjà vu et se reverra !

photo Pass CARTES 2005

A moins d'exploiter la faille de sécurité dont nous venons de parler (ce qui n'est tout de même pas si simple !), explorer des pass de transport basés sur cette technologie ne pourra se faire que dans certaines limites. Nous avons pu vérifier, en effet, que les pass de transport en commun de Varsovie, par exemple, protègent bel et bien la lecture de certains de leurs secteurs par des clefs gardées secrètes. Par contraste, les badges de simple visiteur du salon CARTES (qui sont aussi des Mifare 1K) ont toujours fonctionné avec les clefs par défaut, dites « de transport » ! C'est dire que n'importe qui pourrait lire l'intégralité de leur contenu (ce qui ne serait généralement pas tragique), mais aussi les effacer en tout ou partie pour les réutiliser (ce qui n'est pas forcément inintéressant). D'où l'idée de développer des outils logiciels permettant de manipuler aussi librement que possible, toujours à partir de notre fidèle kit BasicCard (même s'il n'est pas du tout fait pour cela) !

#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 reconnu ! ":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"Barre d'espace pour avancer d'un secteur, Esc pour quitter":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 "Secteur ";SECT;" : clef incorrecte ?";:Goto Jump
If SW1SW2=26514 Then Print "Carte absente !":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 reconnu"
IF T$=Chr$(&H00)+Chr$(&H02) Then Print"MIFARE 4K reconnu"
IF T$=Chr$(&H00)+Chr$(&H26) Then Print"MIFARE Mini reconnu"
IF T$=Chr$(&HF0)+Chr$(&H04) Then Print"TOPAZ ou JEWEL reconnu"
IF T$=Chr$(&HF0)+Chr$(&H11) Then Print"FELICA 212K reconnu"
IF T$=Chr$(&HF0)+Chr$(&H12) Then Print"FELICA 424K reconnu"
IF Left$(T$,1)=Chr$(&HFF) Then Print"Tag 13,56 MHz inconnu"

Quit:
Print:Print:Call WaitForNoCard

Ce premier programme (MIFHEX.BAS) peut lire la totalité de la mémoire d'un Mifare 1K dont les clefs de transport sont restées inchangées. Rappelons que la valeur usuelle, connue de tout un chacun, est FF FF FF FF FF FF (clef par défaut), mais que l'on peut aussi essayer A0 A1 A2 A3 A4 A5 (clef A) ou B0 B1 B2 B3 B4 B5 (clef B). Ces trois valeurs étant pré-programmées dans notre code source, on effacera simplement les lignes inutiles avant compilation, ou on en modifiera l'ordre puisque seule la dernière des trois est prise en compte. Chronologiquement, on commence par charger la clef dans le lecteur (ACR122 installé en tant que lecteur PC/SC N° 1) par une commande LDK (Load Key). Ensuite, le principe consiste à s'authentifier avec cette clef (login) à chaque fois que l'on veut accéder à un nouveau secteur (commande AUT). Bien entendu, des commandes LDK supplémentaires, insérées juste avant chaque commandes AUT, permettraient d'utiliser des clefs différentes pour chaque secteur. Pour peu que la vérification de la clef réussisse, de simples commandes de lecture (RD) suffisent alors pour lire tous les blocs du secteur ainsi ouvert, un appui sur la barre d'espace permettant de passer au suivant. Au total, il y a ainsi 4 blocs à lire dans chacun des 16 secteurs que compte un Mifare 1K, et... quatre fois plus dans un Mifare 4K ! C'est nettement plus que dans un pass Navigo, ce qui permet justement à TFL (Transport For London) d'enregistrer bien davantage d'informations indiscrètes, mais dans un support potentiellement moins sûr.

Certaines applications (salon CARTES, par exemple) enregistrant essentiellement des données alphanumériques dans les Mifare, nous avons créé une variante de notre programme (MIFASC.BAS), qui décode en ASCII les octets que l'on vient y lire. A cette différence près, son fonctionnement est en tout point identique.

#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;" : clef incorrecte ?":Goto Jump
S$="":Call RD(P1P2=SECT*4+BLOCK,S$,Le=&H10)
Print S$

Next BLOCK
Jump:
Next SECT

Print:Print:Call WaitForNoCard

Voyons maintenant (programme MIFWR.BAS) comment écrire dans un Mifare 1K, toujours avec notre ACR122 associé au kit logiciel BasicCard. Là encore, à défaut d'une application pratique bien définie, nous nous bornerons à enregistrer 16 octets ABh dans un bloc (le N° 1 du secteur 15) qui aura été préalablement sauvegardé dans RX$. Après vérification du succès de l'opération (et donc de la validité de la clef employée !), l'état initial sera rétabli (à condition de ne pas retirer prématurément la carte de sur le lecteur...). A noter que le premier bloc (N° 0) de chaque secteur contient des données système, qu'il conviendra de ne pas modifier sans savoir exactement ce que l'on fait (étudier minutieusement la documentation NXP, qui est publiquement disponible) !

#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

Patrick Gueulle

Tous les ouvrages de l'auteur




Vous voulez soutenir une information indépendante ? Rejoignez notre Club privé !


[homepage]  [RSS]  [archives]
[contact & legal & cookies]  [since 1997]