$ k=v p &
[1] 3028
existe-t-il un moyen p
de modifier le contenu de /proc/3028/environ
ne pas le mentionner k=v
pendant qu'il p
est toujours en cours d'exécution?
linux
security
process
linux-kernel
environment-variables
Cetin Sert
la source
la source
Réponses:
Sous Linux, vous pouvez remplacer la valeur des chaînes d'environnement sur la pile.
Vous pouvez donc masquer l'entrée en la remplaçant par des zéros ou toute autre chose:
Courir comme:
le
k=v
a été remplacé par\0\0\0
.Notez que
setenv("k", "", 1)
pour écraser la valeur ne fonctionnera pas comme dans ce cas, une nouvelle"k="
chaîne est allouée.Si vous n'avez pas autrement modifié la
k
variable d'environnement avecsetenv()
/putenv()
, vous devriez également pouvoir faire quelque chose comme ça pour obtenir l'adresse de lak=v
chaîne sur la pile (enfin, l'une d'entre elles):Notez cependant qu'il supprime une seule des
k=v
entrées reçues dans l'environnement. Habituellement, il n'y en a qu'un, mais rien n'empêche quiconque de passer les deuxk=v1
etk=v2
(ouk=v
deux) dans la liste env passée àexecve()
. Cela a été la cause de failles de sécurité dans le passé, comme CVE-2016-2381 . Cela peut réellement se produirebash
avant le shellshock lors de l'exportation à la fois d'une variable et d'une fonction du même nom.Dans tous les cas, il y aura toujours une petite fenêtre pendant laquelle la chaîne env var n'a pas encore été surchargée, donc vous voudrez peut-être trouver un autre moyen de transmettre les informations secrètes à la commande (comme un tube par exemple) si vous l'exposez via
/proc/pid/environ
est une préoccupation.Notez également que contrairement à
/proc/pid/cmdline
,/proc/pid/environment
n'est accessible que par des processus avec le même euid ou racine (ou root uniquement si l'euid et le ruid du processus ne sont pas les mêmes).Vous pouvez leur cacher cette valeur
/proc/pid/environ
, mais ils peuvent toujours obtenir toute autre copie que vous avez faite de la chaîne en mémoire, par exemple en y attachant un débogueur.Voir https://www.kernel.org/doc/Documentation/security/Yama.txt pour savoir comment empêcher au moins les utilisateurs non root de le faire.
la source
Il n'a pas été nécessaire d'écraser les chaînes ci-dessus (pas vraiment sur ) la pile du thread principal sous Linux depuis 2010.
Les deux
/proc/self/cmdline
et/proc/self/environ
sont modifiables par le processus lui-même à l'exécution, à force d'appeler laprctl()
fonction avec respectivementPR_SET_MM_ARG_START
+PR_SET_MM_ARG_END
ouPR_SET_MM_ENV_START
+PR_SET_MM_ENV_END
. Ceux-ci placent directement les pointeurs de mémoire dans l'espace mémoire d'application du processus, détenu par le noyau pour chaque processus, qui sont utilisés pour récupérer le contenu de/proc/${PID}/cmdline
et/proc/${PID}/environ
, et donc la ligne de commande et l'environnement signalés par laps
commande.Il suffit donc de construire un nouvel argument ou une nouvelle chaîne d'environnement (pas de vecteur, remarquez - la mémoire pointée doit être les données de chaîne réelles, concaténées et
␀
délimitées) et d'indiquer au noyau où il se trouve.Ceci est documenté dans la page de manuel Linux pour la
prctl(2)
fonction ainsi que dans laenviron(7)
page de manuel. Ce qui n'est pas documenté, c'est que le noyau rejette toute tentative de définir l'adresse de début au-dessus de l'adresse de fin, ou l'adresse de fin sous l'adresse de début; ou pour (re) remettre à zéro l'une ou l'autre des adresses. De plus, ce n'est pas le mécanisme original proposé par Bryan Donlan en 2009, qui permettait de régler atomiquement le début et la fin en une seule opération. De plus, le noyau ne fournit aucun moyen d' obtenir les valeurs actuelles de ces pointeurs.Il est donc difficile de modifier l'environnement et les zones de ligne de commande avec
prctl()
. Il faut appeler laprctl()
fonction jusqu'à quatre fois car les premières tentatives peuvent entraîner des tentatives pour définir le pointeur de début plus haut que le pointeur de fin, selon l'endroit où les anciennes et les nouvelles données sont en mémoire. Il faut appeler un autre quatre fois si l' on veut faire en sorte que cela ne se traduit pas par une fenêtre d'opportunité pour d' autres processus sur le système pour inspecter une gamme arbitraire du processus espace mémoire dans la période où le nouveau début / fin a été définie mais la nouvelle fin / début ne l'a pas été.Un appel système atomique unique qui définit la gamme entière en une seule fois aurait été beaucoup plus facile à utiliser en toute sécurité pour les programmes d'applications.
Une autre ride est que, sans vraiment bonne raison (compte tenu des contrôles dans le noyau, le overwritability des zones de données originales de toute façon , et le fait que les équivalents ne sont pas des opérations privilégiées sur l' un des BSDs), sur Linux , cela nécessite super - utilisateur privilèges.
J'ai écrit assez simple
setprocargv()
et dessetprocenvv()
fonctions pour mes boîtes à outils, qui emploient cela. Les programmes de chargement en chaîne à partir des jeux d'outils qui sont intégrés, commesetenv
etforeground
, reflètent donc les arguments de commande enchaînés et l'environnement, où Linux le permet.Notez que cela ne milite pas contre les choses qui tracent le processus et accèdent directement à sa mémoire par d'autres moyens (plutôt que via ces deux pseudo-fichiers), et laisse bien sûr une fenêtre avant que les chaînes ne soient modifiées où ces informations peuvent être vues, juste comme l'écrasement des données au-dessus de la pile du thread principal. Et tout comme pour l'écrasement des données, cela ne tient pas compte des bibliothèques d'exécution de langage qui font des copies de l'environnement (sur le tas) dans diverses circonstances. En général, ne considérez pas cela comme un aussi bon mécanisme pour transmettre des "secrets" à un programme que (par exemple) le fait d'hériter d'un descripteur de fichier ouvert à la fin de lecture d'un canal sans nom, lu dans un tampon d'entrée entièrement sous votre contrôle que vous essuyez ensuite.
Lectures complémentaires
la source
/proc/$pid/stat
( en plus d' autres valeurs que vous pourriez avoir besoinstruct prctl_mm_map
). Voir aussi mon exemple filter_env.c pour une petite démo. JdeBP, pouvez-vous ajouter des liens vers vossetprocargv()
/setprocenvv()
fonctions?