VISTA BANK Sécurité des systèmes de paiement
Lab 1 · Travaux pratiques

Anatomie d'une
transaction de paiement

Ce qui circule vraiment sur le réseau quand un client paie —
et ce que le chiffrement protège, ou ne protège pas.

PCI-DSS exigences 3 & 4
Objectif du lab

Voir de ses propres yeux

Personne ne doute qu'il « faut chiffrer ». Mais tant qu'on n'a pas lu un numéro de carte en clair dans un paquet réseau, cela reste une consigne abstraite.

👁 Constater

Intercepter un vrai paiement et y lire le PAN, le CVV et le montant sans aucun outil de déchiffrement.

🔒 Comparer

Rejouer le même paiement sur TLS et observer ce que devient la capture réseau.

🧠 Nuancer

Découvrir ce que TLS ne corrige pas — et pourquoi HTTPS ne vaut pas conformité.

Rappel

Les données du titulaire

 requête de paiement
POST /api/v1/paiement HTTP/1.1 Content-Type: application/json { "pan" : "4532015112830366", "cvv" : "123", "montant" : 250000, "devise" : "GNF", "marchand": "Supermarché Kaloum" }
PAN · Primary Account Number

Le numéro de carte à 16 chiffres. Stockable uniquement s'il est protégé — chiffré, tronqué ou tokenisé.

CVV · Cryptogramme visuel

Interdit de stockage, sans exception — même chiffré, même après une autorisation réussie.

Le raisonnement

PAN + CVV = de quoi payer en ligne à la place du client. C'est pourquoi ces deux données concentrent l'essentiel des exigences.

Le dispositif

Une API bancaire volontairement faillible

une API simule le back-end de paiement de Vista Bank. Il expose trois routes et sait s'écouter sur deux canaux à la fois.

 les trois routes
/api/v1/paiement → reçoit et « autorise » un paiement GET /api/v1/historique → renvoie les 20 dernières transactions GET /api/v1/status → état du service et vulnérabilités
Port 5000 — HTTP

Aucun chiffrement. Tout le contenu circule en texte lisible sur le réseau.

Port 5443 — HTTPS

TLS avec certificat auto-signé, généré par le script au premier lancement.

Même code, même base de données. Seul le canal de transport change — c'est ce qui rend la comparaison honnête.

Mode opératoire

Quatre gestes

1
Lancer les deux serveurs — HTTP sur 5000 et HTTPS sur 5443 en parallèle.
2
Mettre le réseau sur écoute sudo tcpdump -i lo -w /tmp/capture_lab1.pcap 'port 5000 or port 5443'
3
Émettre de vrais paiements bash test_api.sh --both — les mêmes cartes, envoyées sur les deux canaux.
4
Ouvrir la capture dans Wireshark Puis comparer les deux filtres : tcp.port==5000 et tcp.port==5443.

L'interface lo est la boucle locale : le client et le serveur étant sur la même machine, c'est là que passe le trafic. Sur un vrai réseau, ce serait eth0 — et n'importe qui sur le segment verrait la même chose.

Filtre Wireshark · tcp.port==5000

En HTTP : tout est lisible

 Follow → HTTP Stream
POST /api/v1/paiement HTTP/1.1 Host: localhost:5000 Content-Type: application/json Content-Length: 118 {"pan":"4532015112830366","cvv":"123","montant":250000, "devise":"GNF","marchand":"Supermarché Kaloum"} HTTP/1.1 200 OK {"transaction_id":"TXN-6A4EC728","statut":"APPROUVEE", "pan_masque":"************0366"}

Aucun décryptage, aucun outil offensif : le simple fait d'écouter le réseau suffit. La réponse masque poliment le PAN — mais la requête, elle, l'a transporté en entier.

Filtre Wireshark · tcp.port==5443

En HTTPS : plus rien à lire

 Follow → TLS Stream
Transport Layer Security TLSv1.3 Record Layer: Application Data Content Type: Application Data (23) Length: 342 Encrypted Application Data: 17 03 03 01 52 a4 f1 9c 3e 8b 77 d2 04 6f b1 e5 c8 2a 91 db 5f 30 ee 84 19 7c a6 f3 0d 62 bb 4e 8f 21 d7 09 c5 3a 96 e1 74 2f b8 50 dd 13 a9 67… → Ni PAN, ni CVV, ni montant. Seuls restent visibles : les adresses IP, les ports, et le certificat du handshake.

L'écoute passive ne donne plus rien d'exploitable. C'est exactement ce que demande l'exigence 4 de PCI-DSS : chiffrer les données du titulaire lors de leur transmission.

Le même paiement, deux canaux

Face à face

Port 5000 · HTTP
PAN 4532015112830366
CVV 123
Montant 250 000 GNF
Marchand Supermarché Kaloum

Interception triviale. Un poste sur le même réseau, un Wi-Fi partagé, un switch mal configuré : cela suffit.

Port 5443 · HTTPS
a4 f1 9c 3e 8b 77 d2 04
6f b1 e5 c8 2a 91 db 5f
30 ee 84 19 7c a6 f3 0d
62 bb 4e 8f 21 d7 09 c5

Illisible. L'attaquant sait qu'un échange a lieu, avec qui et quand — mais pas ce qu'il contient.

— MÊME CODE · MÊME BASE · SEUL LE TRANSPORT CHANGE —
⚠️ Le moment clé du lab

Alors, problème réglé ?

Interrogeons l'historique après un paiement passé en HTTPS :

 curl -k https://localhost:5443/api/v1/historique
{ "canal" : "HTTPS", "pan" : "4532015112830366", "cvv" : "123", ← stocké en base. En clair. "montant" : 250000 }
TLS protège le transit.
Pas l'application.
Le CVV a voyagé chiffré — puis il a été écrit en base et journalisé en clair, exactement comme en HTTP. Le chiffrement du transport n'a corrigé aucune des violations applicatives.
Diagnostic

Quatre violations PCI-DSS

Exig. 3.2
Le CVV est stocké en base de données Interdit sans exception, y compris après autorisation. C'est la violation la plus grave du lab.
Exig. 3.4
PAN et CVV journalisés en clair Ils apparaissent dans la console du serveur — donc dans les fichiers de logs, souvent recopiés et peu protégés.
Exig. 4.1
Aucun chiffrement du transit (mode HTTP) Seule violation que TLS corrige réellement. Les trois autres lui survivent.
Exig. 7 & 8
L'historique est public Aucune authentification : n'importe qui interroge la route et récupère toutes les cartes.
Et concrètement ?

Ce qu'il aurait fallu faire

Tel quel
stocker(pan, cvv)
log(f"PAN={pan} CVV={cvv}")
GET /historique → public
app.run(port=5000) ← http
Attendu
stocker(token(pan)) # jamais le cvv
log(f"PAN=****{pan[-4:]}")
GET /historique → authentifié
app.run(ssl_context=…) ← tls

🔑 Tokenisation

Remplacer le PAN par un jeton sans valeur hors contexte. Le vrai numéro ne vit que dans un coffre dédié.

🗑 Effacement

Le CVV sert à l'autorisation, puis disparaît. Il n'entre jamais en base, ni en log, ni en sauvegarde.

🛡 Défense en profondeur

TLS, authentification, cloisonnement, journalisation maîtrisée. Aucune mesure ne suffit seule.

Synthèse

Trois idées à emporter

1
Sans chiffrement, il n'y a pas de secret Un paiement en HTTP est une carte bancaire lue à voix haute dans une salle d'attente. Écouter suffit.
2
HTTPS n'est pas la conformité « Le site est en HTTPS » répond à une exigence sur douze. Le stockage, les accès et les traces restent à traiter.
3
La donnée la mieux protégée est celle qu'on ne garde pas Le CVV ne se chiffre pas mieux qu'il ne s'efface. Ne pas conserver, c'est supprimer le risque à la source.
Échangeons

Questions de débriefing

01Dans notre propre système d'information, où transitent aujourd'hui des données de carte sans chiffrement ? Entre applications internes, vers les prestataires, dans les exports ?
02Qui a accès à nos fichiers de logs applicatifs ? Sommes-nous certains qu'aucun PAN complet ne s'y trouve ?
03Si un attaquant obtenait demain une copie de notre base de transactions, que pourrait-il en faire ?
04Nos sauvegardes et nos environnements de test contiennent-ils de vraies données de production ?

Ces questions préparent le Lab 2 — Chiffrement et tokenisation, où nous mettrons en œuvre les protections manquantes

← → naviguer · V vue d'ensemble · F plein écran
VISTA BANK · Lab 1 — Anatomie d'une transaction
1 / 13
Vue d'ensemble — cliquez pour aller à une diapositive