Comment nous avons perdu 230 euros chez CJ Affiliate (Conversant)
[accueil] [menu] [suivez-nous !] [chercher]
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 € !
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...
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 !
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'auteurVous voulez soutenir une information indépendante ? Rejoignez notre
Club privé !
Vous cherchez un ancien numéro ?
Nous avons peut-être un exemplaire pour vous ! !
Certains liens présents dans cette page peuvent être affiliés. Sauf si c'est spécifié dans le texte, cela ne veut pas dire que la rédaction vous recommande les produits/services en question.
[homepage] [RSS] [archives]
[contact & legal & cookies] [since 1997]