Les cartes à puces présentent comme tout système informatiques nombre de failles de sécurité. La majorité d'entre elles étant basée sur une architecture java, elles peuvent présenter des failles de sécurité aussi bien au niveau de la protection cryptographique des données que de l'architecture logicielle de la machine Java utilisée.
En effet, un certain nombre de données doivent être protégées de l'extérieur via des mécanismes de cryptographie. C'est pourquoi les constructeurs et les chercheurs ont imaginé diverses parades contre les attaques qui peuvent être portées contre ces cartes à puces. Ces attaques peuvent être de types divers et attaquer aussi bien la donnée cryptée frontalement qu'en essayant de dévoyer le fonctionnement de la carte pour contourner ces mesures de protections.
Les cartes à puces reposant sur une architecture logicielle, il peut exister certaines failles dans le code des applications intégrées à la carte. Là encore des séries de mesures de protections sont ou peuvent être intégrées afin de combler les failles pouvant être exploitées par des utilisateurs mal intentionnés. En exploitant ces différentes failles, il est possible par exemple de dérober des données, de détourner le fonctionnement normal de la carte, voire de la rendre inopérante.
Il est donc fondamental de connaître et de corriger les différentes failles, afin de protéger au mieux les données sensibles et de garantir le bon fonctionnement de ces cartes à puces.
Problématique de sécurité logicielle
Carte bancaire, carte d’identité, passeport, carte SIM … la liste est grande mais toutes ont un point commun, celui de contenir des données sensibles qui ne doivent être fournies par la puce qu’à des personnes et/ou logiciels autorisés. Ces cartes doivent donc être sécurisées aussi bien d’un point de vue physique que d’un point de vue logiciel. C’est ce dernier point que nous allons explorer ici.
Attaques cryptographiques
Les attaques cryptographiques consistent à essayer de décrypter les mots de passe, les instructions et les processus contenus dans la carte à puce en exploitant soit des algorithmes de déchiffrage, soit les répercussions matérielles de ces données.
Analyse de consommation simple ou différentielle
Selon l'instruction exécutée, le microprocesseur de la carte à puce peut dissiper différentes quantités d’énergies. Une analyse de consommation simple permet donc de donner des informations sur les algorithmes utilisés dans la carte à puce comme une séquence d’instructions. Le SPA est utilisé pour déduire l’implémentation de l’algorithme cryptographique utilisé dans la carte à puce. Dans une attaque SPA, un attaquant observe directement la consommation électrique du système. La quantité d’énergie consommée varie selon l’instruction exécutée dans le microprocesseur. Grâce à cette variation, les grandes fonctions comme les itérations de DES, les opérations de RSA, … peuvent être identifiées. Non seulement les séquences d’instructions peuvent être identifiées mais aussi les instructions individuelles. Dans le cadre d'un algorithme RSA, une attaque SPA peut faire la différence entre une multiplication et une quadrature. De même, dans quelques implémentations de DES, il y a une différence visible entre une permutation et un décalage.
Une analyse différentielle de la consommation est encore plus efficace qu'une analyse de consommation simple, car elle permet en plus d'identifier les bits individuels utilisés dans l’algorithme exécuté. Le fait de révéler chaque bit utilisé donne la possibilité de déduire l’ensemble de clé de chiffrement de l’algorithme. Cette déduction est faite via une analyse statistique de la consommation électrique mesurée pour un grand nombre de calculs avec la même clé de chiffrement. Cette attaque est possible du fait de 3 raisons :
L’encodage binaire des données peut avoir pour conséquence que la consommation électrique soit proportionnel au nombre de changements d’états. La transmission des données dans le bus dissipe la chaleur due à la capacité du fil conducteur. L’activité du bus est mesurée par le poids de Hamming des changements d'états.
En l’utilisant sur les cartes à puces, l’analyse différentielle de consommation permet d’extraire facilement les clés de chiffrements tels que ceux de DES (Data Encryption Standard), AES (Advanced Encryption Standard) ou chiffrement à clé publique. Cette facilité ou efficacité d’extraction repose sur la capacité de l’attaquant à générer correctement la différence de signal qui permet la déduction de la clé de chiffrement .
Cette attaque utilise les matériels physiques pour exploiter le fonctionnement logique de la carte à puce mais elle ne laisse pas de trace sur la carte. Pour cette raison, elle est classée parmi les attaques non invasives . La mesure statistique peut être effectué à l’aide d’un oscilloscope branché sur le lecteur de carte qui va mesurer la différence de consommation électrique lors du chiffrement d’un message.
Attaque par analyse de temps
L'attaque par analyse de temps est basée sur la mesure du temps qu’un algorithme peut prendre pour effectuer une opération. Cette mesure peut être faite par un oscilloscope et peut révéler des informations sur la clé secrète. Par exemple, en mesurant soigneusement le temps sur les opérations de chiffrement, un attaquant peut trouver l’exposant fixe de Diffie-Hellman, la factorisation de RSA ou casser les autres systèmes de chiffrement. Si une unité de cryptographie dans la carte est vulnérable, cette attaque est assez simple et nécessite souvent un cryptogramme connu.
Le temps de traitement d’un système cryptographique se différencie légèrement selon les différentes données en entrée. Cette performance dépend généralement à la fois de la clé de chiffrement et des données en entrée. Un attaquant peut exploiter la mesure de temps pour trouver l’ensemble de la clé secrète.
Dans le système de RSA ou un système de type Diffie-Hellman, comme pour chaque bit à 0 dans le secret exposant, l’ensemble du processus effectue un modulo supplémentaire qui dépend de quelques valeurs intermédiaires, une corrélation peut être observée entre la variation du temps de mesure dans un groupe d’échantillons et le fait qu’un bit dans l’exposant soit à 0 ou non. En appliquant ce processus plusieurs fois, de plus en plus de bits dans l’exposant peuvent être révélés et finalement l’ensemble de la clé est connu. Dans un système à clé symétrique, cette attaque devient plus compliquée mais reste faisable.
Attaques logicielles
Les attaques logicielles tentent de déchiffrer les programmes contenus sur la carte à puce en utilisant des failles dans l'architecture logicielle de celle-ci.
Introduction de code malveillant
Le plus simple moyen d’introduire du code malveillant sur une carte est de créer une application introduisant une faille dans le code et d’installer celle-ci sur la carte. Bien entendu, cette méthode ne marche que sur les cartes ne possédant pas de vérificateur de code.
Le mécanisme d’interface échangeable de la carte est une autre manière d’introduire du code. Ce mécanisme autorise les communications entre les applications, c’est-à-dire qu’il référence les différentes instances des interfaces qui peuvent traverser le pare-feu en toute légalité. Pour l’abuser, il suffit de laisser deux applications communiquer entre elles, mais en générant deux définitions différentes de cette interface de communication. Ainsi, une application malicieuse peut réussir à transférer ou à accéder à des données différentes de celles qui lui étaient initialement autorisées.
Par exemple une application “A” partage un tableau d’entier, alors que l’application “B” partage un tableau de binaires. Dans cette configuration, l’application A peut envoyer des entiers dans le tableau de B, ce qui peut générer des comportements aléatoires sur la carte, ou pour une utilisation plus ciblée d'accéder à des données cachées.
Le mécanisme de transaction permet la transformation des multiples instructions des différents codes en des opérations atomiques, ce qui permet de revenir au point de départ si jamais l’opération est abandonnée.
short[] array1, array2; // instance fields ... short[] localArray = null; // local variable JCSystem.beginTransaction(); array1 = new short; array2 = localArray = array1; JCSystem.abortTransaction();
Dans cet exemple, il est possible que sur certaines cartes les variables array1 et array2 soit effectivement vides, mais que la variable localArray soit toujours utilisable. Il est ainsi possible en multipliant les opérations de faire perdre la trace de ces opérations par le mécanisme. Et donc après le retour en arrière, des références qui auraient dû être nulles ne sont pas effacées. Donc il est possible de rendre égales des variables de types différents.
Détournement de l'utilisation normale d'un tableau
La première utilisation est de convaincre l'application via les méthodes décrites précédemment qu'un tableau de binaires est en réalité un tableau d'entiers. Cela permet d’accéder à des cases de tableau deux fois plus grandes.
Read as byte[] 00 01 02 03 04 05 06 07 ... Read as short[] 0001 0203 0405 0607 ...
Ainsi la case 1 du tableau d'entiers contiendra les cases 1 et 2 du tableau de binaires, et ainsi de suite jusqu’à ce que toutes les valeurs du tableau de binaires soient épuisées, ce qui permettra finalement d’accéder à des binaires appartenant potentiellement à une autre application.
Au lieu de tenter de créer une confusion sur le type des tableaux, on peut tenter de décrire des objets en tableau. Ainsi, n'importe quel objet créé par les développeurs peut être décrypté octet par octet et ainsi être modifié le cas échéant. Il est aussi possible d'intervertir les références de deux objets différents, ce qui peut permettre par exemple de donner l'accès a un objet d'une application à une autre comme si c'était un objet de son propre contexte. Beaucoup plus grave, il est aussi possible d'accéder à l'AID (Applet IDentifier) de chaque application. Ce numéro sert à identifier les applications et doit donc rester fixe. Or si une application malveillante accède à ces numéros, elle peut les corrompre et rendre toutes les applications présentes sur la carte inopérantes.
Problématique du simulateur
Le développement d’application embarquée repose sur l’utilisation de simulateur. En effet ceux-ci s’avèrent très utile pour des développeurs afin de tester leurs codes avant de les déployer sur la plate-forme d’utilisation. Mais ces simulateurs peuvent aussi servir à installer des applications d’un fournisseur sans que celui-ci ne sache que son application est installée sur un tel simulateur, or dans le cas des cartes à puces, une application est censée représenter l’identité de l’utilisateur, spécialement quand la carte à puce est un mécanisme de sécurité permettant d’accéder à des services (financier par exemple), ce qui peut la différer des applications téléphoniques.
De plus ces simulateurs ne peuvent fonctionner que dans le cas d’un fonctionnement dit UCOM, pour User Centric Ownership Model (Modèle de possession centrée sur l’utilisateur). En effet ce modèle est opposé à l’ICOM, Issuer Centric Smart Card Ownership Model (Centrée sur l'émetteur) et qui donc ne délègue la tâche d’installation des applications à l’entreprise distribuant la carte, modèle largement représenté dans le domaine bancaire par exemple. Ce modèle délègue donc la tâche d’installation à l’utilisateur, il ne peut donc s’assurer correctement de la bonne utilisation de ses services, d’autant plus que des problématiques de protection des données des utilisateurs peuvent se poser dans ce cas.
Grâce à de tel types de simulateur, il est possible de procéder à trois types d’attaques différentes :