Comment les signaux * nix vous permettent de lire la mémoire d'autres processus

Il y a une chose très ancienne et enracinée * nix appelée "signaux" . L'idée derrière ces primitives est très simple: implémenter un logiciel analogique d'interruptions. Différents processus peuvent s'envoyer des signaux les uns aux autres et à eux-mêmes, connaissant l'identifiant de processus (pid) du destinataire. Le processus de réception est libre d'attribuer une fonction de gestionnaire de signal qui sera automatiquement appelée lors de sa réception, ou de l'ignorer à l'aide d'un masque spécial, ou de faire confiance au comportement par défaut. Jusqu'ici tout va bien.



Comportement par défaut à la réception d'un signal ... Que signifient ces mots rassurants? Pas ce à quoi vous vous attendiez, bien sûr. Le wiki dit que les 28 gestionnaires de signaux par défaut (il y en a d'autres!) Sont les suivants: 2 sont ignorés, 4 provoquent l'arrêt du processus, 1 pour continuer, 11 pour se terminer, 10 pour se terminer avec un vidage de mémoire. Maintenant c'est intéressant! Donc, la situation est la suivante: même si votre programme ne mentionne aucun signal dans le code source, en fait il les utilise, et de manière très dramatique.



À partir de maintenant, nous devrons creuser plus profondément. Qui peut envoyer des signaux et à qui? Le wiki dit: "Un processus (ou un utilisateur shell) avec un UID effectif différent de 0 (UID superutilisateur) ne peut envoyer des signaux qu'aux processus avec le même UID. Donc, si vous exécutez 100 programmes, chacun d'entre eux peut facilement tuer tous ces 100 programmes en utilisant l'API système, même si tous les programmes (à l'exception du tueur) ne mentionnaient aucun signal dans leur code source. Si vous avez travaillé sous le compte root, peu importe qui a démarré certains processus, vous pouvez toujours les terminer facilement. Il est, bien sûr, possible de découvrir le pid d'un processus spécifique et d'exécuter son "assassinat contractuel", mais il est encore plus facile de tuer tous ceux qui peuvent être simplement des pid-s de force brute.



«Attendez, attendez, ne conduisez pas les chevaux. Vous avez mentionné que les signaux peuvent être traités et ignorés! " - J'entends la voix de mon lecteur. Que dira Vicki? "Pour un traitement alternatif de tous les signaux sauf SIGKILL et SIGSTOP, un processus peut affecter son propre gestionnaire ou ignorer leur occurrence en modifiant son masque de signal." Nous regardons les actions par défaut lors de la réception de ces signaux et voyons: "Terminer le processus", "Terminer le processus". Il s'avère que nous pouvons faire ces deux actions chaque fois que l'envoi de signaux SIGKILL et SIGSTOP à la victime est en principe possible. "La seule exception est un processus avec pid 1 (init), qui est autorisé à ignorer ou à gérer tous les signaux, y compris KILL et STOP."Nous ne pourrons peut-être même pas tuer l'un des processus système les plus importants en tant que root, mais à l'amiable, cela nécessite des recherches supplémentaires.



Eh bien, l'image est devenue un peu plus positive, mais elle est toujours sombre. Si vous démarrez un processus, il est garanti qu'il peut se terminer et arrêter un tas d'autres processus. Lorsqu'une condition très simple est remplie, "les développeurs du processus de réception ont oublié d'ignorer ou de gérer en quelque sorte l'un des nombreux autres signaux", l'application maniaque sera en mesure de provoquer la fin du processus avec un vidage de la mémoire ou de continuer le processus après son arrêt. Si les développeurs de l'application réceptrice ont accroché leurs gestionnaires sur certains signaux, vous pouvez essayer d'interférer avec le fonctionnement de cette application en lui envoyant des signaux. Ce dernier sujet fait l'objet d'une discussion séparée, car en raison de l'exécution asynchrone des gestionnaires, des courses et un comportement indéfini sont possibles ...



«Le raisonnement abstrait est très cool, mais rapprochons-nous des détails», me dira un lecteur exigeant. Ok, pas de problème! Tout utilisateur de * nix est familier avec un programme comme bash. Ce programme se développe depuis près de 30 ans et offre toute une montagne de possibilités. Remplissons-la pour plus de clarté et tirons un peu de sa mémoire!



Je prends mon Ubuntu 16.04.2 domestique hors de la jambe large et j'exécute deux copies de bash 4.3.46 dessus. Dans l'un d'eux, j'exécuterai une commande hypothétique avec des données secrètes: export password = SECRET. Oublions un instant le fichier avec l'historique des commandes, dans lequel le mot de passe serait également écrit. Dans la même fenêtre, tapez la commande ps pour trouver le pid de ce processus - disons 3580.



Sans fermer la première fenêtre, passons à la seconde. La commande ps qu'il contient donnera un autre pid de cette instance de bash - disons 5378. Juste pour plus de clarté, c'est à partir de cette deuxième bash que nous enverrons un signal à la première commande kill -SIGFPE 3580. Oui, cher lecteur, c'est une absurdité totale: le processus 2 ne dit rien concernant pour traiter 1, que dans ce même processus 1, une opération arithmétique erronée s'est produite. La fenêtre suivante apparaît à l'écran: L'







anomalie souhaitée s'est produite lors de la création d'un vidage mémoire, c'est-à-dire que bash ne semble pas traiter ou ignorer ce signal. En cherchant sur Google où je devrais chercher la décharge, j'ai trouvé une réponse détaillée ( un , deux). Dans mon Ubuntu, la situation est la suivante: si une application du package standard plante en raison d'un signal autre que SIGABRT, alors le vidage est transféré vers le programme Apport. C'est juste notre cas! Ce programme assemble un fichier avec des informations de diagnostic et affiche la fenêtre ci-dessus. Le site officiel déclare fièrement: «Apport collecte des données potentiellement sensibles, telles que les vidages de mémoire, les traces de pile et les fichiers journaux. Ils peuvent contenir des mots de passe, des numéros de carte de crédit, des numéros de série et d'autres documents privés. " Alors, je me demande, mais où avons-nous ce fichier? Oui, /var/crash/_bin_bash.1000.crash. Tirons son contenu dans le dossier somedir: apport-unpack /var/crash/_bin_bash.1000.crash somedir. En plus de diverses petites choses inintéressantes, il y aura un vidage de mémoire convoité appelé CoreDump.



Le voici, le moment de vérité! Cherchons dans ce fichier la chaîne de mot de passe et voyons ce qui nous intéresse en réponse. Commande Strings CoreDump | grep password rappellera au hacker oublieux que le mot de passe est SECRET. Formidable!



J'ai fait la même chose avec mon éditeur de texte préféré gedit, en commençant à taper dans le tampon, puis en le lisant depuis le vidage. Aucun problème! À ce stade, Vicki a chuchoté dans son oreille d'avertissement: «Parfois (par exemple, pour les programmes exécutés au nom du super-utilisateur), un vidage de mémoire n'est pas créé pour des raisons de sécurité. Soooo, vérifions ... Lors de la réception d'un signal du root bash, le second root bash s'est écrasé avec la création d'un vidage mémoire, mais à cause des permissions (-rw-r ----- avec le propriétaire de root) il n'est plus aussi facile de le lire que les précédents appartenant à mon compte utilisateur. Eh bien, si le programme tueur hypothétique a réussi à envoyer un signal à partir de l'UID du superutilisateur, alors il peut toucher un tel vidage.



Le lecteur méticuleux peut remarquer: "Il vous a été très facile de trouver les données que vous cherchiez dans la mer des ordures." C'est vrai, mais je suis sûr: si vous savez quel type de poisson vous voulez attraper et où il nage, le trouver dans les filets à benne devrait être réaliste presque toujours. Par exemple, personne ne prend la peine de télécharger un package contenant des informations de débogage pour un programme en panne et de découvrir le contenu des variables qui vous intéressent dans GDB par le débogage post-mortem.



Tout cela peut sembler assez inoffensif, mais en fait ce n'est pas le cas. Toutes les actions que j'ai décrites pourraient facilement être effectuées par un programme ou un script s'exécutant en mode utilisateur, sans parler d'un niveau d'accès plus privilégié. En fin de compte, un exécutable malveillant peut facilement couper les programmes à droite et à gauche, et souvent aussi lire librement toute leur mémoire. Voici les signaux et les rapports de bogues! Je suis sûr que sur d'autres plates-formes * nix et avec d'autres programmes destinataires, la situation est similaire, mais bien sûr je ne la vérifierai pas.



L'objection peut surgir: le malware peut simplement utiliser les outils de débogage pour extraire des données intéressantes de l'application. Ça l'est vraiment. Pourquoi, alors, est ce poste? Mon point est le suivant: la première chose qui me vient à l'esprit lorsque l'on essaie d'arrêter le vol de données dans les applications, ce sont simplement les limitations des outils de débogage. Les outils antivirus attrapent sûrement l'utilisation de ptrace () en premier lieu - c'est un événement très suspect. Les signaux sont une tout autre affaire. Un processus envoie à un autre un signal standard - et alors? À première vue, c'est un événement tout à fait normal. Mais, comme nous l'avons déjà vu, cela peut conduire à une interruption anormale de l'application, créant un vidage de mémoire dans un dossier, à partir duquel il peut être essayé de l'extraire.



Quand j'ai essayé d'ouvrir la page de connexion de vk.com et de vider Firefox avec le même signal fatal, il s'est écrasé, mais a appelé son gestionnaire de vidage. Les vidages au format minidump délicat sont enregistrés dans ~ / .mozilla / firefox / Crash Reports / {en attente ou soumis} et nécessitent une enquête plus approfondie. Voici ce que vous découvrirez si, dans la fenêtre des paramètres, cliquez sur "En savoir plus" en face de la coche (le texte ci-dessous était accroché sur www.mozilla.org/ru/privacy/firefox/#crash-reporter ):







« Mozilla Firefox. , Firefox, , URL- , . , , . crash-stats.mozilla.com. . .»Il y a rarement quelque chose de vraiment savoureux dans les URL, mais s'il y a des mots de passe ou des cookies dans les décharges est une bonne question!



Sur cette note mystérieuse et intrigante, je terminerai. J'ai reçu un signal que j'ai oublié de traiter explicitement.



PS J'ai écrit un programme simple avec un tel gestionnaire de signaux SIGUSR1: imprimez la chaîne "1" sur l'écran, entrez une boucle sans fin. J'espérais que si vous envoyez le signal SIGUSR1 plusieurs fois à ce programme, le gestionnaire sera appelé plusieurs fois, ce qui entraînera un débordement de pile. Malheureusement pour moi, le gestionnaire n'a été appelé qu'une seule fois. Bon, écrivons un gestionnaire similaire pour le signal SIGUSR2 et envoyons deux signaux différents dans l'espoir que cela videra la victime ... Hélas, cela n'a pas aidé non plus: chaque gestionnaire n'a été appelé qu'une seule fois. Débordé, débordé, mais n'a pas débordé!



PS 2. Dans le monde de Windows, il existe une sorte de signaux - des messages qui peuvent être envoyés à Windows . Il est très probable qu'ils puissent également être utilisés pour le plaisir et le profit!



L'original a été publié sur mon blog 05/05/17.



All Articles