J'ai remarqué il y a quelque temps que les noms d'utilisateur et les mots de passe donnés en curl
tant qu'arguments de ligne de commande n'apparaissent pas dans la ps
sortie (bien qu'ils puissent bien sûr apparaître dans votre historique bash).
De même, ils n'apparaissent pas dans /proc/PID/cmdline
.
(La longueur de l'argument combiné nom d'utilisateur / mot de passe peut cependant être dérivée.)
Démonstration ci-dessous:
[root@localhost ~]# nc -l 80 &
[1] 3342
[root@localhost ~]# curl -u iamsam:samiam localhost &
[2] 3343
[root@localhost ~]# GET / HTTP/1.1
Authorization: Basic aWFtc2FtOnNhbWlhbQ==
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: localhost
Accept: */*
[1]+ Stopped nc -l 80
[root@localhost ~]# jobs
[1]+ Stopped nc -l 80
[2]- Running curl -u iamsam:samiam localhost &
[root@localhost ~]# ps -ef | grep curl
root 3343 3258 0 22:37 pts/1 00:00:00 curl -u localhost
root 3347 3258 0 22:38 pts/1 00:00:00 grep curl
[root@localhost ~]# od -xa /proc/3343/cmdline
0000000 7563 6c72 2d00 0075 2020 2020 2020 2020
c u r l nul - u nul sp sp sp sp sp sp sp sp
0000020 2020 2020 0020 6f6c 6163 686c 736f 0074
sp sp sp sp sp nul l o c a l h o s t nul
0000040
[root@localhost ~]#
Comment cet effet est-il atteint? Est-ce quelque part dans le code source de curl
? (Je suppose que c'est une curl
fonctionnalité, pas une ps
fonctionnalité? Ou est-ce une fonctionnalité du noyau?)
Aussi: cela peut-il être réalisé en dehors du code source d'un exécutable binaire? Par exemple, en utilisant des commandes shell, probablement combinées avec des permissions root?
En d'autres termes, pourrais-je en quelque sorte masquer un argument d'apparaître dans /proc
ou dans une ps
sortie (même chose, je pense) que j'ai passé à une commande de shell arbitraire ? (Je suppose que la réponse à cette question est "non", mais il semble utile d'inclure cette demi-question supplémentaire.)
environ
directement pour accéder aux variables d'environnement? - la ligne du bas: la liste des arguments, comme la liste des variables d'environnement, est en mémoire en lecture / écriture dans le processus utilisateur et peut être modifiée par le processus utilisateur.grep
modèle une classe de caractères. Par exempleps -ef | grep '[c]url'
curl
correspondcurl
mais[c]url
ne correspond pas[c]url
. Si vous avez besoin de plus de détails, posez une nouvelle question et je me ferai un plaisir de vous répondre.Réponses:
Lorsque le noyau exécute un processus, il copie les arguments de la ligne de commande dans la mémoire en lecture-écriture appartenant au processus (sur la pile, au moins sous Linux). Le processus peut écrire dans cette mémoire comme n'importe quelle autre mémoire. Lorsque
ps
affiche l'argument, il lit tout ce qui est stocké à cette adresse particulière dans la mémoire du processus. La plupart des programmes conservent les arguments originaux, mais il est possible de les changer. La description POSIX desps
états quiCela s'explique par le fait que la plupart des variantes Unix reflètent le changement, mais que les implémentations POSIX sur d'autres types de systèmes d'exploitation ne le peuvent pas.
Cette fonctionnalité est d'une utilité limitée car le processus ne peut pas effectuer de modifications arbitraires. À tout le moins, la longueur totale des arguments ne peut pas être augmentée, car le programme ne peut pas modifier l'emplacement où
ps
aller chercher les arguments et ne peut pas étendre la zone au-delà de sa taille d'origine. La longueur peut effectivement être réduite en plaçant des octets nuls à la fin, car les arguments sont des chaînes terminées par un octet nul (style C) (il est impossible d’avoir un groupe d’arguments vides à la fin).Si vous voulez vraiment creuser, vous pouvez regarder la source d'une implémentation open-source. Sous Linux, la source de
ps
n'est pas intéressante, tout ce que vous verrez ici est qu’elle lit les arguments de la ligne de commande à partir du système de fichiers proc , dans . Le code qui génère le contenu de ce fichier se trouve dans le noyau, dans . La partie de la mémoire du processus (accessible avec ) va de l'adresse à ; ces adresses sont enregistrées dans le noyau au démarrage du processus et ne peuvent plus être modifiées par la suite./proc/PID/cmdline
proc_pid_cmdline_read
fs/proc/base.c
access_remote_vm
mm->arg_start
mm->arg_end
Certains démons utilisent cette possibilité pour refléter leur statut, par exemple, ils changent leur
argv[1]
chaîne en une chaîne telle questarting
ouavailable
ouexiting
. Beaucoup de variantes unix ont unesetproctitle
fonction pour le faire. Certains programmes utilisent cette possibilité pour masquer des données confidentielles. Notez que son utilisation est limitée car les arguments de la ligne de commande sont visibles au démarrage du processus.La plupart des langages de haut niveau copient les arguments dans des objets chaîne et ne permettent pas de modifier le stockage d'origine. Voici un programme en C qui démontre cette capacité en modifiant
argv
directement des éléments.Exemple de sortie:
Vous pouvez voir la
argv
modification dans le code source de curl. Curl définit une fonctioncleanarg
danssrc/tool_paramhlp.c
laquelle est utilisé pour changer un argument à tous les espaces en utilisantmemset
. Danssrc/tool_getparam.c
cette fonction est utilisée plusieurs fois, par exemple par expurger le mot de passe utilisateur . Comme la fonction est appelée à partir de l'analyse des paramètres, elle se produit tôt dans une invocation curl, mais le vidage de la ligne de commande avant que cela se produise affichera toujours les mots de passe.Étant donné que les arguments sont stockés dans la mémoire du processus, ils ne peuvent pas être modifiés de l'extérieur, sauf en utilisant un débogueur.
la source
ps
arguments de rapport de cette partie de la mémoire du noyau, en ignorant les modifications apportées à la mémoire en lecture-écriture des processus? Mais (si j'ai bien compris?) La plupart des variantes UNIX ne font même pas la première, vous ne pouvez donc pas faire d'ps
implémentation la dernière sans modification du noyau, puisque les données d'origine ne sont conservées nulle part?argv
modifier le contenu des entrées (vous ne pouvez pas définirargv[i]
, mais vous pouvez écrire jusqu'auargv[i][0]
boutargv[i][strlen(argv[i])]
), il doit donc y avoir une copie dans la mémoire du processus.ps
sortie, beaucoup d’arguments vides semblent ne pas y être, mais oui, cela fait une différence si vous vérifiez le nombre d’espaces disponibles et que vous pouvez observer plus directement depuis/proc/PID/cmdline
.Les autres réponses répondent bien à la question de manière générale. Pour répondre spécifiquement " Comment cet effet est-il obtenu? Est-il quelque part dans le code source de curl? ":
Dans la section d'analyse des arguments du code source curl , l'
-u
option est gérée comme suit:Et la
cleanarg()
fonction est définie comme suit:Ainsi, nous pouvons voir explicitement que l'argument nom d'utilisateur: mot de passe dans
argv
est remplacé par des espaces, comme décrit dans les autres réponses.la source
cleanarg
états indique explicitement qu'il fait ce que la question demande!Un processus peut non seulement lire ses paramètres, mais aussi les écrire.
Je ne suis pas un développeur, je ne suis donc pas familier avec ce genre de choses, mais cela peut être possible de l'extérieur avec une approche similaire au changement de paramètres d'environnement:
https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables
la source
bash -c 'awk 1 /proc/$$/cmdline; set -- something; awk 1 /proc/$$/cmdline'
, cela montre qu'au moins dans le shell, la définition des paramètres est différente de la modification de ce que le noyau considère comme les paramètres du processus.