J'utilise Terminal sous Mac OS X depuis des années, mais j'ai en quelque sorte manqué de repérer cette fonctionnalité:
Je me demande maintenant comment cela fonctionne, et est-ce sûr à 100%? Si ce n'est pas le cas, quelle technique pourrait-on utiliser pour toujours obtenir les touches?
"Secure Keyboard Entry" correspond à la fonction EnableSecureEventInput
dont le concept est décrit ici . Fondamentalement, les applications n'accèdent pas au matériel elles-mêmes; ils obtiennent événements (par exemple sur les touches) du système d'exploitation. Certains éléments du système d'exploitation décident quelle application obtient quels événements, en fonction de ses droits d'accès et de l'état de l'interface graphique (il y a des détails selon l'application qui est "au premier plan").
Les applications peuvent "s'espionner", ce qui signifie (dans ce cas) qu'une application s'exécutant sur la machine peut demander au système d'exploitation de lui envoyer une copie de tous les coups de touches même s'ils sont destinés à une autre application et/ou à injecter événements synthétiques qui lui sont propres. Il s'agit d'une fonctionnalité: il permet des choses comme les "portefeuilles de mots de passe" (qui saisissent un mot de passe comme s'il avait été tapé par l'utilisateur, du point de vue de l'application) ou le "Visualiseur de clavier" "(le clavier basé sur une interface graphique qui vous permet de" taper "des caractères avec la souris et montre également quelles touches sont réellement pressées à tout moment). EnableSecureEventInput
bloque cette fonctionnalité pour l'application qui l'appelle. Essayez! Exécutez Terminal.app, activez le "Keyboard Viewer" et vérifiez que l'activation de "Secure Keyboard Entry" empêche le Keyboard Viewer de faire son travail.
Tous ces routages d'événements sont effectués dans un processus de l'espace utilisateur qui s'exécute comme root
. Ceci repose sur la séparation de processus imposée par le noyau: le processus utilisateur normal ne peut pas jouer à volonté avec la mémoire allouée pour un processus racine. Le noyau lui-même ne connaît pas le concept au niveau de l'utilisateur d '"événement". La gestion des événements, en particulier l'application (ou non) de EnableSecureEventInput
, est faite par du code non noyau.
Un extrait intéressant de la page liée ci-dessus est le suivant:
L'implémentation d'origine de
EnableSecureEventInput
était telle que lorsqu'un processus permettait une entrée d'entrée sécurisée et avait le focus clavier, les événements clavier n'étaient pas transmis aux processus d'interception. Cependant, si le processus d'entrée sécurisée était déplacé en arrière-plan, le système continuerait de transmettre les événements de clavier à ces processus d'interception, car le focus du clavier n'était plus sur un processus d'entrée sécurisée.Récemment, une faille de sécurité a été trouvée qui permettait à un processus d'interception de capturer les événements du clavier, même dans les cas où la saisie d'événements sécurisés était activée et le processus d'entrée d'événements sécurisés était en arrière-plan. La solution à ce problème consiste à cesser de transmettre des événements de clavier à tout processus d'interception chaque fois qu'un processus a activé l'entrée d'événements sécurisés, que ce processus soit au premier plan ou en arrière-plan. Cela signifie qu'un processus qui permet une entrée d'événement sécurisée et laisse une entrée d'événement sécurisée activée pendant la durée du programme, peut affecter tous les processus d'interception du clavier, même lorsque le processus d'événement sécurisé a été déplacé en arrière-plan.
Cela signifie que le système de routage d'événements s'est réellement trompé lors du premier versement de la fonctionnalité. Ceci est maintenant censé être corrigé.
Même en supposant que le routage des événements est maintenant correct et sécurisé, ce qui signifie que la sémantique de EnableSecureEventInput
est vraiment appliquée, alors vous devez comprendre que c'est complètement par rapport au système de séparation de processus. Tout processus racine peut inspecter et modifier à volonté la mémoire de tous les autres processus, et notamment voir tous les événements; et un processus racine peut également se connecter au noyau et inspecter les données réelles du clavier en contournant complètement la notion d'événement. Un enregistreur de frappe qui peut être installé en tant que root fera exactement cela, et "Secure Keyboard Entry" sera sans défense contre lui. Voir this pour une preuve de concept open source.
Ainsi, "Secure Keyboard Entry" est sécurisé uniquement contre les attaquants qui pourraient exécuter leur propre code sur la machine, mais ne peuvent pas augmenter leurs privilèges locaux au niveau racine. Il s'agit d'un scénario plutôt restrictif, car l'escalade de privilèges locaux a tendance à être possible sur une base générale:
Le processus local peut voir une grande partie de la machine, donc le "périmètre de sécurité" à défendre est énorme dans ce cas. Empêcher l'intrusion des attaquants à distance est beaucoup plus facile, et pourtant déjà assez difficile.
Apple a tendance à montrer une certaine manque de réactivité dans le cas de trous d'escalade de privilèges locaux.
Résumé: Je trouverais trop optimiste de croire que "Secure Keyboard Entry" offre une sécurité suffisante contre les enregistreurs de frappe sur, disons, les ordinateurs publics partagés. Ce n'est pas une mauvaise fonctionnalité, mais elle ne remplit ses promesses que si root et le noyau sont exempts d'altérations malveillantes, et c'est un très gros "si".
Il y a autre chose qui mérite d'être gardé à l'esprit - et, il me semble, peu apprécié: sur les systèmes POSIX, tout terminal possède son propre périphérique de "télétype". Et chaque processus que vous exécutez peut lire à partir de cet appareil, , que vous activiez ou non "Secure Keyboard Entry" (Linus Åkesson donne un résumé de comment les systèmes Unix gèrent les terminaux .)
Les noms et autorisations de ces appareils varient d'un système à l'autre. macOS, à partir de la version 10.14, les nomme tty[p-w][0-f]{1,3}
et accorde un accès en lecture/écriture à l'utilisateur qui exécute le terminal (et un accès en écriture seule aux membres du groupe tty
).
Vous pouvez l'essayer vous-même en activant "Secure Keyboard Entry" dans, disons iTerm.app , en appelant tty
pour voir le terminal il utilise, puis ouvre, disons Terminal.app et lit à partir de cet appareil en utilisant cat
. Vous constaterez que iTerm.app reçoit certains caractères et Terminal.app autres.