Comme je l'ai écrit mardi, ma banque me fait désormais utiliser une saloperie de clavier virtuel pour saisir mon mot de passe de connexion à mon espace client sur son site web. Un mot de passe d'exactement 8 chiffres… Une saloperie de clavier qui fait chier en réduisant le confort d'utilisation tout en diminuant la sécurité du client que je suis.
Un des points clés permettant de comprendre la diminution de la sécurité, c'est que ça fait belle lurette que les logiciels malveillants ne sont plus bloqués par les claviers virtuels. Il y a une multitude de méthodes pour récupérer le mot de passe malgré eux. Il y a les extensions malveillantes pour navigateurs web conçues pour retrouver la correspondance clic->image->chiffre. Il y a la traditionnelle capture vidéo de l'affichage. Il y a aussi la traditionnelle interception des flux réseaux, y compris ceux chiffrés (genre HTTPS). Les antivirus et les serveurs mandataires (proxy) d'entreprise / d'administration font ça depuis belle lurette aussi. Analyse HTTPS qu'ils disent. Pour notre sécurité qu'ils disent. Rien de nouveau : quand un attaquant est à l'une ou l'autre des extrémités d'une communication, il peut tout faire sans avoir à se donner la peine de casser le chiffrement soutenant la communication.
J'ai eu envie de voir le clavier virtuel de ma banque sous l'angle d'une interception du trafic HTTPS. Évidemment, sur mon propre identifiant + mot de passe, tout ça, tout ça.
Ça se fait très bien avec mitmproxy
. J'ai découvert cet outil dans une causerie de l'ami Aeris au nom évocateur : Comment powned une application bancaire en 30 minutes.
On installe mitmproxy sur un système Debian GNU/Linux : sudo apt-get install mitmproxy
.
On l'exécute : mitmproxy --socks
ou mitmweb --socks
si l'on veut l'interface web en suplément. --socks
active le mode proxy SOCKS. Plusieurs modes sont disponibles.
Le certificat d'une autorité de certification x509 maison est automatiquement généré dans .~/mitmproxy/mitmproxy-ca-cert.pem
. On l'importe dans le catalogue des autorités de certification reconnues de notre navigateur web (Firefox : Édition -> Préférences -> Vie privée et sécurité -> Certificats -> Afficher les certificats -> Autorités -> Importer… -> choisir -> Confirmer cette AC pour identifier des sites web -> OK). J'utilise un profile Firefox vierge (firefox -p
pour en créer un) afin de ne pas pourrir le mien et pour que seul le site web de ma banque soit intercepté (ça rend l'analyse plus lisible, moins de flux interceptés).
Pour simplifier, je configure mitmproxy comme proxy SOCKS (127.0.0.1:8080) de mon navigateur web (Firefox : Édition -> Préférences -> Général -> bouton « Paramètres… » dans la rubrique « Paramètres réseau ». Comme ça, je n'ai pas besoin de conduire une "vraie" attaque de l'homme du milieu (sinon j'aurais choisi une machine virtuelle configurée en passerelle réseau de mon ordinateur et, pour une vraie de vraie attaque MitM, j'aurai sorti ettercap
). Et ça nous permet de vivre comment agit un proxy installé dans une entreprise / administration au nom de la prétendue sécurité de celle-ci et au détriment de la vie privée des employés. ;)
Je me connecte au site web de ma banque. Je saisis mon identifiant et je valide le formulaire. Ho, une requête HTTP POST a été capturée par mitmproxy
. Son contenu :
{
"validate": {
"<identifiant_unique_de_la_transaction>": [
{
"id": "<identifiant_unique_de_la_transaction>",
"login": "toto",
"type": "IDENTIFIER"
}
]
}
}
Intéressant (oui, j'avais bien saisi « toto » comme identifiant).
Le clavier virtuel s'est affiché. Je saisis mon code et je valide. Nouvelle requête HTTP POST :
{
"validate": {
"<identifiant_unique_de_la_transaction>": [
{
"type":"PASSWORD",
"id":"<identifiant_unique_de_la_transaction>",
"password":"9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 0711f5af-3e90-449f-bbe9-c55f08450a7d 92e47c70-00ab-4b88-95af-ab19cbad6644"
}
]
}
}
On voit clairement qu'il y a 8 groupes de blocs de chiffres… Comme les 8 chiffres de mon mot de passe.
Si mon navigateur web a émis ceci, c'est qu'il a été préalablement informé de la marche à suivre. Il y a forcément une convention entre le serveur de ma banque et mon navigateur web. Regardons les échanges précédents dans mitmproxy
:
GET […]/api/v1u0/medias/images/imgb6ad9545-e3be-455f-9dd6-7b9e0de59c25 Content-Type: image/png
GET […]/api/v1u0/medias/images/imgb7f60f3f-5dff-4ba8-a85c-9fbf938c03e0 Content-Type: image/png
GET […]/api/v1u0/medias/images/img32e8d95a-67b7-409a-92ae-e200aedb0961 Content-Type: image/png
GET […]/api/v1u0/medias/images/img9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 Content-Type: image/png
GET […]/api/v1u0/medias/images/img8971b94e-7f4c-49c1-acb4-bce2b0db4498 Content-Type: image/png
GET […]/api/v1u0/medias/images/img0711f5af-3e90-449f-bbe9-c55f08450a7d Content-Type: image/png
GET […]/api/v1u0/medias/images/img4710dc98-9eae-4492-9cd3-a8250ee7c827 Content-Type: image/png
GET […]/api/v1u0/medias/images/img92e47c70-00ab-4b88-95af-ab19cbad6644 Content-Type: image/png
GET […]/api/v1u0/medias/images/img93292639-12e1-45c8-ba22-16107ad657d3 Content-Type: image/png
GET […]/api/v1u0/medias/images/img9d799ee1-166a-43af-a750-bbe3e7286c6b Content-Type: image/png
Ho bah dis donc, 10 fichiers image, comme les 10 chiffres du clavier virtuel ! Exemple : le fichier img9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 est une image du chiffre 6. Des fichiers son sont nommés selon la même nomenclature. Exemple : /api/v1u0/medias/sounds/snd9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 = chiffre 6. Ils sont utilisés par la version du clavier virtuel accessible aux handicapés visuel.
Hum, dis donc, le nom d'un fichier contient un bloc de chiffres qui ressemble à ceux du JSON, non ? C'est bien ça. 9ad8e027-86d9-4f9e-8ae9-3114e6c6bc78 = 6. Donc mon mot de passe est 666666XX . 0711f5af-3e90-449f-bbe9-c55f08450a7d représente un 4 et 92e47c70-00ab-4b88-95af-ab19cbad6644 un 2. Donc mon mot de passe est 66666642. C'est bien ce que j'avais saisi sur le clavier virtuel, en tout cas.
Pour info, le nom des fichiers images change à chaque tentative de saisie d'un mot de passe, tout de même.
Évidemment, l'utilisation de mitmproxy
est de trop puisque les outils de dév' de Firefox permettent de voir le nom des images ainsi que le mot de passe encapsulé en JSON dans la requête POST. Mais ça nous a fourni un alibi pour jouer avec mitmproxy
. :D
Du coup, ouais, n'importe quelle saloperie installée dans le navigateur web a accès à mon mot de passe, en JS ou autre… Et c'est à peine plus difficile à enregistrer que le contenu d'un champ XHTML standard. Les claviers virtuels, c'est du pipeau.