Réaliser un lecteur de badge avec rasberry pi (Partie 2)

raspberry-ban

Introduction

La semaine dernière, nous en étions restés à la compilation de la librairie libnfc. Si vous avez besoin de vous rafraîchir la mémoire c’est par ici. Aujourd’hui nous allons voir comment lire un badge tel que les badges d’entrée d’immeuble avec un programme en C qui tournera sur raspberry Pi.

Lecture de l’uid

Tout d’abord, il est important de savoir que seul un numéro de série est lu par beaucoup de lecteurs de cartes pour le contrôle d’accès. Ceci n’est absolument pas sécurisé et il est possible d’acheter des cartes (sur le marché chinois) permettant de copier ces badges en utilisant le programme d’exemple nfc-mfsetuid disponible dans le dossier exemple. D’ailleurs, les serruriers ne font qu’une simple copie de votre badge vers un nouveau avant de le verrouiller en écriture.

Il serait tout a fait possible de réaliser un protocole sécurisé mais pour cela, il faudrait des badges équipés de capacité cryptographique et donc plus chers. Les badge d’entrée les plus fréquemment utilisés sont des badges Mifare qui ne coûtent vraiment pas grand chose : MIFARE 4K NXP blanche haute qualité Par 5000 = 0.90 € unitaire trouvé sur google.

Nous allons faire comme eux et simplement lire l’uid. Nous ne prétendrons cependant pas que ce soit sécurisé. Pour cela allons dans le dossier exemples/ et lançons le programme suivant :

sudo ./nfc-poll

Et voilà vous venez de lire l’UID de votre badge !

Code C

Nous allons maintenant repartir du programme nfc-poll afin de le personnaliser et de le réutiliser dans notre application. Toujours dans le dossier exemple :

mkdir badgeReader/utils/
cp nfc-poll.c badgeReader/badgeReader.c
cp ../utils/nfc-utils.h examples/badgeReader/utils/
cp ../utils/nfc-utils.c examples/badgeReader/utils/
cd badgeReader/
gcc badgeReader.c utils/nfc-utils.c -lnfc -o myBadgeReader.o
sudo ./myBadgeReader

Félicitation, vous venez de compiler votre première application avec libnfc. Je vous conseille de garder ce squelette de coté, il constitue une bonne base pour commencer avec le NFC.

Vérifier l’UID

Bien, pour l’instant, nous ne faisions que d’afficher l’UID en réutilisant les programmes déjà présents. nous allons maintenant le récupérer et le comparer afin de vérifier si la personne est autorisée à entrer ou non.

Copier le squelette précédemment construit et remplacer le fichier badgeReader.c par celui écrit ci dessous :

/**
 * @file badgeReader.c
 * @brief read a badge and print a message if the badge is the one attended
 */
 
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
 
#include <nfc/nfc.h>
#include <nfc/nfc-types.h>
 
#include "utils/nfc-utils.h"
 
static nfc_device *pnd = NULL;
 
int main(int argc, const char *argv[])
{
	const unsigned char referenceUID[7] ={0x04, 0x3c,  0x76,  0x7a,  0xa6,  0x27,  0x80};
	const unsigned char referenceUIDsz = 7;	
 
	const unsigned char uiPollNr = 20;
	const unsigned char uiPeriod = 2;
 
	/* Defines the modulation types
	 * for the mifare types, only the type A is requested */
	const nfc_modulation nmModulations[1] = {
		{ .nmt = NMT_ISO14443A, .nbr = NBR_106 },
	};
 
	int i;
	const size_t szModulations = 1;
 
	nfc_target nt;
	int res = 0;
 
	nfc_context *context;
	nfc_init(&context);
 
	/* We open the pn53x */
	pnd = nfc_open(context, NULL);
 
	if (pnd == NULL) {
		ERR("%s", "Unable to open NFC device.");
		exit(EXIT_FAILURE);
	}
 
	if (nfc_initiator_init(pnd) < 0) {
		nfc_perror(pnd, "nfc_initiator_init");
		exit(EXIT_FAILURE);
	}
 
	if ((res = nfc_initiator_poll_target(pnd, nmModulations, szModulations, uiPollNr, uiPeriod, &nt))  < 0) {
		nfc_perror(pnd, "nfc_initiator_poll_target");
		nfc_close(pnd);
		nfc_exit(context);
		exit(EXIT_FAILURE);
	}
 
	if (res > 0) {
		printf("Read UID     : ");
		print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
		printf("Expected UID : ");
		print_hex(referenceUID, referenceUIDsz);
 
	} else {
		printf("No target found.\n");
	}
	nfc_close(pnd);
	nfc_exit(context);
	exit(EXIT_SUCCESS);
}

Vous pouvez maintenant comparer vos deux UID dans un programme.

Conclusion

Pourquoi ne pas ajouter un module comme celui ci à votre raspberry pi et continuer les développement vers quelques chose de plus sécurisé avec l’ajout d’un code PIN par exemple.

It’s oversimple, isn’t it?

Réaliser un lecteur de badge avec rasberry pi (Partie 1)

raspberry-ban

Introduction

Un article en deux parties.Une première cette semaine pour vous expliquer comment installer la librairie sur votre raspberry pi. Le prochain article décrira comment réaliser un programme en C pour lire un badge de type badge d’entrée des immeubles.

La librairie libnfc

La librairie libnfc est une librairie dédiée à la communication en NFC. Cette librairie est publieé sous licence LGPL (libre de droit pour les applications libres ou commerciales).

Celle-ci fonctionne avec un hardware spécifique, on peut trouver la liste sur le wiki de libnfc.

Pour ma part, j’ai un dongle usb équipé d’un PN533 (fabriqué par NXP). La photo est ci dessous :

dongle_pn533.jpg

Télécharger la librairie

Les liens du wiki officiel sont brisés mais une petite recherche google nous permet de retrouver la release. Pour les projets sur le Pi, privilégiez les versions packagées aux versions développeurs.

wget https://libnfc.googlecode.com/files/libnfc-1.7.0-rc3.tar.gz
tar -xvzf libnfc-1.7.0-rc3.tar.gz 
cd libnfc-1.7.0-rc3/

Configuration

Si vous souhaitez configurer la librairie pour un pn532 en UART comme ceux de chez Adafruit il va falloir commencer par libérer l’UART du pi comme indiqué dans cette article :

Puis une fois l’UART libéré, il va falloir copier le fichier de configuration comme suit :

sudo mkdir -p /etc/nfc/devices.d
sudo cp contrib/libnfc/pn532_uart_on_rpi.conf.sample /etc/nfc/devices.d/pn532_uart_on_rpi.conf

Editez ensuite le fichier suivant :

sudo nano /etc/nfc/devices.d/pn532_uart_on_rpi.conf

Et modifiez la ligne suivante à la fin du fichier

allow_intrusive_scan = true

Compilation

Enfin nous pouvons maintenant compiler les sources :

./configure --with-drivers=pn532_uart --sysconfdir=/etc --prefix=/usr
autoreconf -vis
make clean
sudo make install

Et pour tester :

cd utils/
sudo ./nfc-scan-devices

Et vous devriez voir apparaître quelque chose comme ça :

1 NFC device(s) found:
- NXP / PN533:
    pn53x_usb:002:003

Conclusion

En attendant l’article de la semaine prochaine (il est déjà écrit, il ne reste qu’à le mettre en page), vous pouvez parcourir le dossier exemple/. Vous y trouverez de quoi vous amusez un peu avec diverses badges du quotidien.

Attaque sur carte sans contact

Un petit retour sur le workshop de la Nuit du Hack.

La démonstration principale de ce workshop était une attaque sur les cartes sans contact. Celles-ci proposent de payer en sans contact à une distance d’une dizaine de centimètre du lecteur. Ce paiement ne nécessite pas de saisir son code PIN. Il est cependant limité à des transactions d’un montant maximal de 20€ et à 4 transactions consécutives. Après il faut passer en mode contact pour réaliser une transaction.

Description de l’attaque

L’idée est de réaliser un proxy permettant de faire une transaction à distance.

explain

Le téléphone est un téléphone NFC qui permet de réaliser des transactions en sans contact. Celui-ci est relié par un réseau, par exemple un réseau internet, à un lecteur de carte sans contact. Ce lecteur dans le schéma est représenté à droite à coté du personnage en costume. Il est relié à un ordinateur afin de pouvoir être accessible depuis un réseau.

Nous aurions aussi pu utiliser un autre téléphone NFC à la place du couple PC – lecteur sans contact. Cependant je n’avais à ma disposition qu’un seul téléphone NFC.

L’attaque consiste à réaliser un proxy passif afin de réaliser un paiement à l’aide d’une carte qui ne se trouve pas à proximité du lecteur. Puisque la technologie est sans contact, cela peut être réalisé à l’insu de la cible.

Réalisation

Afin de réaliser cette attaque, un téléphone Nexus S a été utilisé. Ce téléphone possède une puce NFC et permet l’installation de l’application simply tap avec une cyanogen mod 9.1. Cette application permet d’avoir accès à l’antenne NFC du téléphone depuis une application android. Le but premier est de réaliser des services de paiement en cloud.

Dans notre cas, au lieu d’interroger un cloud, nous interrogeons un lecteur distant afin de dialoguer directement avec une carte sans contact.

Démonstration :


Attaque par proxy par oversimple

Comment s’en protéger

Pour s’en protéger, c’est assez simple il suffit de mettre sa carte dans un étui en fer. Il existe des portes feuilles blindés qui font très bien l’affaire.

Bibliographie

SimplyTapp NFC Payment System Debuts with CyanogenMod 9.1
emulating pki smart card with cm9.1
NFC Proxy

Nuit du Hack 2k13

ndh

Un petit bilan de la nuit du hack.

Un petit retour sur la Nuit du hack qui vient de se passer. Cette année les confs étaient essentielement en anglais. On peut y voir une volontée de s’ouvrir de plus en plus vers l’étranger.

Le thème du SE est revenu assez fréquement. On a eu comme toujours le droit à notre lot de surprises. Nous avons une petite préference pour les techniques roumaines de fraudes bancaires sur internet.

L’idée est simple, convertir des euro en leu roumain (l’argent roumain) et utiliser les arrondis du troisième digit pour se retouver avec un arrondi supérieur en notre faveur. Ce qui est amusant c’est de voir comment avec ingéniosité il a automatisé les vérifications du code secret qui valide les transactions. Ses automates valent le détour.

Sinon, Julien a présenté un workshop sur le NFC. Le workshop s’est bien déroulé et nous avons pu établir quelques contacts. C’est assez suprenant de voir que les gens s’intéressent autant à la technologie.

Après tout ça on est allé faire un petit tour dans les jardins du parcs avant que les gardes nous demandent de rentrer dans nos hotels. Pour le coup, on ne comprend vraiment pas pourquoi.

DSCF1115

On postera d’autre trucs plus tard sur le workshop et les challenges du wargames mais pour l’instant il est l’heure d’aller se coucher.

Espionner une transaction Monéo

La carte Monéo

La carte Monéo est un porte monnaie électronique. La spécificité d’un porte monnaie électronique est que l’argent n’est pas présent directement sur la carte.

Pour la Monéo, il est nécessaire de présenter votre carte bancaire. Une transaction est effectuée de la même manière que si vous retiriez de l’argent en liquide. Cet argent est alors inscrit sur la carte Monéo. Monéo propose un service de chargement en ligne. Nous allons en profiter pour observer la manière dont fonctionne le chargement d’une telle carte.

L’espion de carte à puce

L’espion fonctionne à partir d’un microprocesseur Microchip PIC32MX512L. Pour plus de détails sur le développement :

Le protocole ISO7816 a été implémenté afin de pouvoir obtenir des traces qui ressemblent à ceci :

T=1:

ATR : 3BE800008131FE454A434F505632343194
Term (S-block):
00C101 FC 3C
Card (S-block):
00E101 FC 1C
Term (I-block):
00000C 00A4040007A0000000041010 0F
Card (I-block):
000025 6F218407A0000000041010A516500A4F56455253494D504C45BF0C07636172647370799000 C3
Term (I-block):
004005 00C0000041 C4

T=0:

ATR : 3B 66 00 00 90 D1 02 01 20 B1 
Term (CLA INS P1 P2 P3):
00 A4 04 0C 06 
Card (Ack):
A4 
Term (UDC):
A00000006900
Card (SW): 
9000
Term (CLA INS P1 P2 P3):
00 B2 01 BC 16
Card (ACK UDR SW): 
B2 9250003840106021502D15091207010250455552011C 9000

Le chargement Monéo

A l’aide de l’espion, nous observons un chargement de Monéo de dix euros effectué sur internet.

Celui ci se décompose en deux parties, la première partie est une lecture des informations de la carte, numéro de PAN, solde etc…

Ensuite un série de commandes est exécutée de cla E0 et d’instructions 30.
La classe E0 nous indique alors qu’il s’agit d’une carte supportant jusqu’à 16 canaux logiques (16 pointeurs de fichier) et que la commande inclus du Secure Messaging.

Edition après le commentaire de SV :

Une petite remarque en passant: CLA = E0 signifie surtout que le bit de poids fort est à 1 donc l’instruction (et la classe) sont propriétaires. La norme ISO/IEC 7816 ne s’applique donc pas pour interpréter l’octet CLA (en particulier les 16 canaux).

Autrement dit, le chargement est protégé par un calcul de MAC. Le mac faisant 8 octets de long, on peut vraisemblablement penser à du 3-DES.

Term (CLA INS P1 P2 P3):
E0 30 00 00 1C 
Card (ACK):
30 
Term (UDC):
00000000001000000000000000007001070600018820121121192244
Card (SW)
6139 
Term (CLA INS P1 P2 P3):
00 C0 00 00 39 
Card (ACK UDR SW):
C0 010005010010000021108888866666001000315D110004010010000100000030000000000000000000000000000000000DCE86FF2230D6A91B 9000
Term (CLA INS P1 P2 P3):
E0 30 80 00 35
Card (ACK):
30 
Term (UDC):
10000501001000250001700107060000000000018820121121192244010000003000000000000000000000000DAE7D69BE5F4394EA 
Card (UDR):
610D 
Term (CLA INS P1 P2 P3):
00 C0 00 00 0D 
Card (ACK UDR SW):
C0 11000501001000003110000000 9000

Conclusion

On retrouve dans la dernière UDC la date de la transaction ainsi que le montant. La sécurité du mécanisme repose la génération des macs par le serveur. Ceci est un système sécurisé à condition que les algorithmes cryptographiques soient correctement implémentés.

Interroger une carte à puce avec Java et un lecteur PC/SC

Utiliser la librairie smartcardio de java

La librairie smartcardio permet de comuniquer entre un lecteur pcsc et une application java.
Ceci peut ouvrir la voie à des applications sécurisées par carte à puce. Les cartes à puce permettent de stocker des clés cryptographiques de manière sûre.

Pour l’installation des drivers PC/SC direction cet article : http://oversimple.fr/espionner-une-transaction-avec-carte-a-puce/

Utilisation de la librairie dans eclipse

De base la librairie n’est pas accessible. Pour contourner ce problème, copier le code ci dessous dans une classe java :

/**
 * @param args
 */
public static void main(String[] args) {
	try {
		/* Affiche la liste des lecteurs PCSC */
		TerminalFactory factory = TerminalFactory.getDefault();
		List terminals = factory.terminals().list();
		System.out.println("Terminals: " + terminals);
 
		/* Selectionne le premier lecteur */
		CardTerminal terminal = terminals.get(0);
 
		/* Etablit la connection avec la carte */
		Card card = terminal.connect("*"); 
		/* '*' Laisse le programme choisir le mode de communication */
		System.out.println("card: " + card);
		CardChannel channel = card.getBasicChannel();
 
		// disconnect
		card.disconnect(false);
	} catch (CardException e) {
		e.printStackTrace();
	}
}

Vous devriez avoir l’erreur suivante.

Pour y parer, suivez les étapes décrites ci dessous :

On supprime alors la librairie java.

It’s OverSimple isn’t it?

Synchronisation sur un protocole bas niveau

Nous sommes en mesure d’espionner les premières transactions. Il ne nous reste plus qu’à configurer l’affichage sur la dalle tactile. Cet article va présenter la façon dont nous avons choisi de nous synchroniser avec le signal que nous espionnons. Cette méthode peut être extrapolée à d’autres protocoles de communication.

Synchronisation entre l’espion, le terminal et la carte

Les communications avec cartes à contact suivent la norme iso7816. Les communications sont réalisées en passant, sur la ligne, un état haut ou un état bas. Ce niveau logique doit être appliqué pendant une certaine durée; la durée de transmission d’un caractère. Afin de faire simple, cette durée dépend de la fréquence d’horloge appliquée à la carte par le terminal.

On peut le définir tel que :

Tc = a*f 
où :
f est la fréquence
Tc est la durée d'un caractère
a est un facteur de proportionnalité

Le temps que dure un caractère peut changer durant la transmission mais il sera toujours fonction de la fréquence. Pour le modifier, la carte demande à ce que se soit la valeur de a qui évolue.

Une explication plus détaillée (et surtout plus juste) est faite dans la norme iso 7816 ou bien dans l’EMV book 1 téléchargeable sur le site d’EMVco : http://www.emvco.com/specifications.aspx?id=223

Trame observée

La première action consistait à visualiser le signal obtenu. Pour ce faire,  j’ai décortiqué la norme et pris un oscilloscope. Dans le cas étudié, la première chose transmise est un octet décrivant le codage des caractères (Big endian / Little endian). Il est transmis par la carte et ressemble à ceci :

On remarque alors qu’aux temps t1 et t2, nous avons, bien que le caractère soit différent, un front descendant. Ceci correspond, d’après la norme, à la transmission de trois bits. Nous allons donc nous synchroniser sur ces deux fronts descendants lancer un compteur de temps et diviser le résultat par trois afin d’obtenir la durée de transmission d’un bit.

Code

Nous codons ceci sur un micro-contrôleur pic32. Le modèle de notre PIC est le pic32mx795F512L.
Configuration de l’interruption qui doit se déclencher sur les fronts descendants:

 /* Configure the interupt on IO to answer on each falling edge*/
    ConfigINT2(EXT_INT_ENABLE | FALLING_EDGE_INT | EXT_INT_PRI_1);

Implémentation de l’interruption pour lancer le timer 1 lors du premier front descendant puis le couper lors du second.

unsigned int state = 0;
unsigned int bitDuration = 0;
 
/* INT2 ISR */
/* Interruption externe 2 */
void __ISR(_EXTERNAL_2_VECTOR, IPL1) _Int2Handler(void) {
 
    /* State = 0 il s'agit du premier front descendant */
    if(0 == state)
    {
        /* Configure le Timer1*/
        mT1ClearIntFlag();
        /*Lance le timer 1 */
        OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_1, 64000);
        state = 1;
    }
    else if(1 == state)
    {
          ConfigIntTimer1(T1_INT_OFF);
          bitDuration = ReadTimer1()/3;
    }
    /*Efface le flag d'interruption*/
    mINT2ClearIntFlag();
}

bitDuration contient alors le nombre de coups de clock que l’on doit compter pour obtenir le temps de transmission d’un bit.

It’s OverSimple, isn’t it?