Blog of :/blog/weboob/Vérification_des_certificats.html

Vérification des certificats

Jusqu'alors, un problème dans la sécurité de Weboob est qu'il ne vérifie pas la validité du certificat envoyé par le serveur lorsqu'on établie une connexion SSL. Ceci est dû à l'utilisation de mechanize, la bibliothèque qui simule le comportement d'un navigateur, et qui n'offre pas de tel mécanisme.

L'écriture par Laurent du Browser 2 se passant de mechanize pour le remplacer astucieusement par requests devrait résoudre ce problème proprement dans une prochaine version de Weboob. Malheureusement, ce nouveau browser n'étant pas encore terminé, une solution alternative et provisoire a été proposée par Florent.

Comme mechanize a une gestion opaque du SSL (du fait des multiples couches le séparant de la bibliothèque openssl, et de la médiocrité du code), l'idée est d'établir une première connexion en utilisant directement openssl et de valider le certificat à partir du fingerprint préalablement renseigné dans le module, avant de poursuivre le déroulement normal via mechanize.

Cette mesure de protection peut facilement être contournée, puisqu'il suffit à l'attaquant, dans le cas d'un Man-in-the-middle, de relayer la première connexion, et de s'interposer pour les suivantes qui elles ne seront pas vérifiées par mechanize.

Néanmoins, ce mécanisme temporaire est efficace dans la plupart des cas.

Pour les développeurs de modules, il suffit de renseigner au BaseBrowser l'attribut de classe CERTHASH contenant le SHA-256 de la chaîne de certificats du serveur :

class BNPorc(BaseBrowser):
    DOMAIN = 'www.secure.bnpparibas.net'
    PROTOCOL = 'https'
    CERTHASH = '5511f0ff19c982b6351c17b901bfa7419f075edb13f2df41e446248beb7866bb'

Une autre façon de faire est d'appeler directement la méthode StandardBrowser.lowsslcheck :

browser.lowsslcheck('www.secure.bnpparibas.net', '5511f0ff19c982b6351c17b901bfa7419f075edb13f2df41e446248beb7866bb')

Afin de calculer ce fingerprint, vous pouvez aisément procéder de la manière suivante :

$ python
Python 2.7.3rc2 (default, Apr 22 2012, 22:30:17)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> from hashlib import sha256
>>> domain = 'www.secure.bnpparibas.net'
>>> sha256(ssl.get_server_certificate((domain,  443))).hexdigest()
'5511f0ff19c982b6351c17b901bfa7419f075edb13f2df41e446248beb7866bb'

Bien évidement, il vaut mieux être certain de ne pas soi-même être victime d'une attaque à ce moment là, car aucune vérification n'est effectuée.

Il ne s'agit que d'une mesure temporaire, en attendant mieux dans le Browser 2.