La situation ne s'arrête pas aux serveurs PostgreSQL : la plupart des clients SQL populaires seraient plus que favorables aux connexions non chiffrées sans avertissement. Jonathan Mortensen et son équipe ont mené une enquête informelle auprès de 22 clients SQL populaires et ont constaté que seuls deux d'entre eux exigent des connexions chiffrées par défaut. Six autres demandent le chiffrement, mais acceptent en sourdine une connexion non chiffrée. Les 14 clients restants demandent à l'utilisateur d'opter pour l'utilisation de SSL ; les connexions sont non chiffrées par défaut.
« Lorsque vous vous connectez à un site Web avec votre navigateur, les données que vous envoyez et recevez sont probablement chiffrées. Il est donc étonnant que les données envoyées vers et depuis les serveurs PostgreSQL connectés à Internet soient très probablement non chiffrées. C'est un problème », écrit Jonathan Mortensen. « Nous avons vu des millions de tentatives de connexion à bit.io au cours du mois dernier. La raison principale pour laquelle ces tentatives échouent est qu'elles n'utilisent pas de chiffrement (ce que nous exigeons) », poursuit-il.
Il y a beaucoup de serveurs PostgreSQL connectés à l'Internet : une recherche sur shodan.io montre un échantillon de plus de 820 000 serveurs PostgreSQL connectés à l'Internet entre le 1er et le 29 septembre. Seuls 36 % des serveurs examinés disposaient de certificats SSL. Plus de 523 000 serveurs PostgreSQL en écoute sur Internet n'utilisaient pas SSL (64 %), laissant ouverte la possibilité d'une lecture indésirable des données transmises vers et depuis le serveur. Pire encore, 41 serveurs PostgreSQL en ligne n'étaient absolument pas protégés, ne disposant même pas d'un mot de passe.
Certificats autosignés et expirés
Il ne suffit pas d'avoir un certificat. Près de 12 000 (4,0 %) des certificats étaient expirés. En outre, plus de 128 000 (43,3 %) des certificats étaient autosignés. Les connexions aux serveurs avec des certificats autosignés sont chiffrées, mais les certificats ne confèrent souvent pas de confiance : généralement, ils ne sont ni émis ni validés par une autorité de certification, ils n'expirent pas et ne peuvent pas être révoqués. La plupart des clients ne disposent pas d'un certificat racine pour un certificat autosigné donné, ils ne peuvent donc pas se connecter en utilisant verify-full, sans lequel les clients sont sujets à des attaques de type man-in-the-middle.
La majorité des serveurs PostgreSQL connectés à Internet ne prennent pas en charge le chiffrement
Cela nous laisse 160 310 serveurs PostgreSQL avec des certificats qui ne sont ni expirés ni autosignés. Le chiffrement des connexions à ces serveurs n'est toujours pas garanti, car de nombreux clients PostgreSQL n'activent pas les connexions SSL par défaut, et ceux qui le font ne valideront pas nécessairement le certificat du serveur par défaut. De même, les serveurs PostgreSQL qui prennent en charge SSL et disposent de certificats SSL valides n'exigent pas toujours que ces certificats soient utilisés. La prise en charge du chiffrement semble être mieux que rien, mais étant donné les valeurs par défaut non sécurisées des clients, ce n'est pas beaucoup mieux que l'absence de chiffrement.
Déduire si SSL est nécessaire à partir des messages d'erreur de connexion
Nous pouvons en apprendre un peu plus sur les exigences de chiffrement des serveurs PostgreSQL en examinant les messages d'erreur renvoyés lorsqu'un client tente de se connecter à chaque serveur. Shodan scanne chaque IP avec un client libpq configuré pour "préférer" SSL (mais en passant un nom de base de données de template0, un nom d'utilisateur de postgres, et aucun mot de passe). Lorsqu'il est configuré en mode "prefer", le client essaiera de se connecter à nouveau si la première tentative qui demandait le SSL donne lieu à une erreur. Nous avons utilisé le contenu des erreurs, en combinaison avec la présence/absence d'un certificat, pour déduire le statut de support SSL de ces serveurs PostgreSQL.
Au maximum, environ 14 % des serveurs PostgreSQL connectés à Internet requièrent le SSL. 23% supportent le chiffrement mais ne l'exigent pas
Nous avons constaté que, sur les quelque 820 000 serveurs PostgreSQL de l'enquête, 64 % ne prenaient pas en charge SSL. 23 % supportaient, mais n'exigeaient pas l'utilisation de SSL. Seuls 7 % d'entre eux exigeaient probablement ou certainement le cryptage. Pour les autres 7 %, nous avons pu établir que SSL était supporté, mais nous n'avons pas pu faire d'autres déductions quant à la nécessité de son utilisation.
C'est un triste état de fait. La grande majorité des serveurs PostgreSQL qui écoutent sur Internet ne prennent pas du tout en charge les connexions cryptées ou bien ils prennent en charge le cryptage, mais acceptent le trafic non crypté. Il y a pire : les clients SQL ont le choix d'utiliser ou non le chiffrement lorsqu'ils se connectent à un serveur PostgreSQL, et la plupart d'entre eux sont plus qu'heureux de ne pas le faire. Pour comprendre ce comportement peu sûr, nous devons prendre un moment pour comprendre comment SSL fonctionne réellement avec PostgreSQL.
Voici, quelques principes de fonctionnement des connexions SSL dans PostgreSQL
- Le client et le serveur ont tous deux leur mot à dire quant à l'utilisation du chiffrement. Si le client tente d'établir une connexion cryptée, le serveur peut accepter ou refuser cette demande. Le client peut alors choisir d'accepter une connexion non chiffrée ou d'abandonner. Si le client demande une connexion non cryptée, le serveur peut choisir d'accepter cette connexion ou de l'abandonner ;
- La validation du certificat, le processus par lequel le client détermine si le certificat présenté par le serveur est légitime, est également configurable. La validation du certificat a lieu pendant la poignée de main TLS. Elle empêche les serveurs malveillants de se faire passer pour le véritable serveur auquel un client avait l'intention de se connecter (attaque de type man-in-the-middle). Il s'agit d'une exigence pour une connexion réellement sécurisée ;
- « Votre client ne vous dira probablement pas si votre connexion est non chiffrée », souligne Jonathan Mortensen. Vous avez peut-être remarqué qu'il y a plusieurs chemins qui sautent SSL alors qu'un seul chemin (le client et le serveur acceptant une connexion SSL) démarre une connexion SSL chiffrée. La plupart des clients PostgreSQL ont un paramètre, souvent nommé sslmode, qui spécifie le(s) chemin(s) à essayer. De nombreux clients SQL sont configurés par défaut pour ne pas tenter de connexion chiffrée du tout ou pour revenir silencieusement à une connexion non chiffrée si le serveur ne supporte pas SSL.
La bibliothèque PostgreSQL standard pour Python est psycopg (2 et 3), qui utilise libpq, donc son mode par défaut est de préférer ssl. Cela signifie que les méthodes de connexion tenteront d'abord une connexion chiffrée, mais se rabattront ensuite sur une méthode non cryptée si le serveur ne supporte pas SSL. Les autres bibliothèques de langage : jdbc, npgsql, node-postgres et pgx - ont SSL désactivé par défaut, l'utilisateur est donc responsable de la configuration du chiffrement.
MySQL
MySQL utilise une sécurité basée sur des listes de contrôle d'accès (ACL) pour toutes les connexions, requêtes et autres opérations que les utilisateurs peuvent tenter d'effectuer. Il existe également un support pour les connexions chiffrées par SSL entre les clients et les serveurs MySQL. La plupart des concepts abordés ici ne sont pas du tout spécifiques à MySQL ; les mêmes idées générales s'appliquent à presque toutes les applications.
Lorsque vous vous connectez à un serveur MySQL, vous devez utiliser un mot de passe. Le mot de passe n'est pas transmis en clair lors de la connexion. Toutefois, les autres informations sont transférées sous forme de texte et peuvent être lues par toute personne capable de surveiller la connexion. Si la connexion entre le client et le serveur passe par un réseau non fiable et que cela inquiète, il est possible d’utiliser le protocole compressé pour rendre le trafic beaucoup plus difficile à déchiffrer. Il est également possible d’utiliser le support SSL interne de MySQL pour rendre la connexion encore plus sûre. Il est également possible d’utiliser SSH pour obtenir une connexion TCP/IP chiffrée entre un serveur MySQL et un client MySQL.
Avec une connexion non chiffrée entre le client MySQL et le serveur, une personne ayant accès au réseau pourrait observer tout le trafic et inspecter les données envoyées ou reçues entre le client et le serveur. Les algorithmes de chiffrement doivent inclure des éléments de sécurité pour résister à de nombreux types d'attaques connues, comme la modification de l'ordre des messages chiffrés ou la relecture des données.
MySQL prend en charge les connexions chiffrées entre les clients et le serveur à l'aide du protocole TLS (Transport Layer Security). TLS est parfois appelé SSL (Secure Sockets Layer) mais MySQL n'utilise pas réellement le protocole SSL pour les connexions chiffrées, car son chiffrement est faible. TLS utilise des algorithmes de chiffrement pour garantir la fiabilité des données reçues sur un réseau public. Il dispose de mécanismes pour détecter la modification, la perte ou la relecture des données. TLS intègre également des algorithmes qui permettent la vérification de l'identité à l'aide de la norme X.509.
La norme X.509 permet d'identifier une personne sur Internet. En termes simples, il doit exister une entité appelée « autorité de certification » (ou CA) qui attribue des certificats électroniques à toute personne qui en a besoin. Les certificats s'appuient sur des algorithmes de chiffrement asymétrique qui possèdent deux clés de chiffrement (une clé publique et une clé secrète). Le propriétaire d'un certificat peut présenter le certificat à une autre partie comme preuve d'identité. Un certificat est constitué de la clé publique de son propriétaire. Toute donnée chiffrée à l'aide de cette clé publique ne peut être déchiffrée qu'à l'aide de la clé secrète correspondante, qui est détenue par le propriétaire du certificat.
Le support des connexions chiffrées dans MySQL est assuré par OpenSSL. Rappelons que OpenSSL est une boîte à outils de chiffrement comportant deux bibliothèques, libcrypto et libssl, fournissant respectivement une implémentation des algorithmes cryptographiques et du protocole de communication SSL/TLS, ainsi qu'une interface en ligne de commande, Openssl. Développée en C, OpenSSL est disponible sur les principaux systèmes d'exploitation et dispose de nombreux wrappers ce qui la rend utilisable dans une grande variété de langages informatiques. Utilisé par deux tiers des sites Web en 2014, la documentation d’OpenSSL a augmenté de 94 % depuis OpenSSL 1.1.1 et le nombre de « lignes de code » dans nos tests a augmenté de 54 % (après ajustement).
Par défaut, les instances MySQL se lient à une bibliothèque OpenSSL installée et disponible au moment de l'exécution pour la prise en charge des connexions chiffrées et d'autres opérations liées au chiffrement. Il est possible de compiler MySQL à partir des sources et utiliser l'option CMake WITH_SSL pour spécifier le chemin d'accès à une version particulière d'OpenSSL installée ou à un paquetage système OpenSSL alternatif. Dans ce cas, MySQL sélectionne cette version.
De MySQL 8.0.11 à 8.0.17, il était possible de compiler MySQL en utilisant wolfSSL comme alternative à OpenSSL. À partir de MySQL 8.0.18, le support de wolfSSL est supprimé et toutes les compilations MySQL utilisent OpenSSL. Si MySQL est compilé avec une version d'OpenSSL et que l’utilisateur souhaite passer à une autre version sans recompiler, il peut le faire en modifiant le chemin du chargeur de bibliothèque dynamique (LD_LIBRARY_PATH sur les systèmes Unix ou PATH sur les systèmes Windows). Supprimez le chemin d'accès à la version compilée d'OpenSSL, et ajoutez le chemin d'accès à la version de remplacement, en la plaçant avant toute autre bibliothèque OpenSSL sur le chemin d'accès. Au démarrage, lorsque MySQL ne trouve pas la version d'OpenSSL spécifiée avec WITH_SSL sur le chemin, il utilise la première version spécifiée sur le chemin à la place.
Par défaut, les programmes MySQL tentent de se connecter en utilisant le chiffrement si le serveur supporte les connexions chiffrées, et reviennent à une connexion non chiffrée si une connexion chiffrée ne peut être établie. MySQL effectue le chiffrement sur une base par connexion, et l'utilisation du chiffrement pour un utilisateur donné peut être facultative ou obligatoire. Cela permet de choisir une connexion chiffrée ou non chiffrée en fonction des exigences des applications individuelles.
Source : Jonathan Mortensen
Et vous ?
Pensez-vous que l'analyse de Jonathan Mortensen est pertinente, pourquoi ?
Croyez-vous que MySQL est plus fiable et robuste que PostgreSQL ? Dans quelle mesure ?
Avez-vous une expérience sur ces deux SGBD ? Un autre que ces deux-là ? Quelle est votre appréciation ?
Quel SGBD conseillerez-vous pour une utilisation en toute sécurité sur Internet ?
Voir aussi :
OpenSSL annonce la disponibilité de la version 3.0 et le renouvellement de la Licence Apache-2.0, avec l'utilisation du nouveau module FIPS dans les projets de développement d'applications
PostgreSQL : Supabase annonce la mise en libre accès de Postgres-wasm, un serveur PostgreSQL qui fonctionne dans un navigateur
PostgreSQL aurait commencé à travailler sur le support de la compression Zstandard, pour compléter toutes les possibilités de LZ4 que l'on trouve actuellement dans PostgreSQL 14