Un programme peut-il dire qu'il est exécuté sous sudo?

27

J'ai un programme qui devrait se comporter différemment s'il est exécuté sous "sudo". Existe-t-il un moyen de savoir s'il a été exécuté sous sudo?

Mise à jour: quelqu'un a demandé pourquoi je voudrais faire cela. Dans ce cas, sur un Mac utilisant MacPorts, une sortie vous indique de couper-coller une commande particulière. Si la commande MacPorts a été exécutée avec "sudo", elle doit inclure sudo dans l'exemple de commande:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)
TomOnTime
la source
Je suis curieux: pouvez-vous expliquer comment cela devrait se comporter différemment?
sciurus
1
@sciurus, le cas d'utilisation courant se trouve généralement dans un script d'installation qui nécessite des privilèges root; si vous ne les avez pas, mourez immédiatement.
Nick T
3
Cela ressemble à meta.stackexchange.com/questions/66377/what-is-the-xy-problem/… . Qu'est-ce que tu veux vraiment faire?
Jenny D dit Réintégrer Monica le
Je me souviens vaguement d'une commande sachant qu'elle est exécutée en tant que root ou non ... Je pense que la réponse est "oui"
Rolf

Réponses:

48

Oui, 4 variables d'environnement sont définies lorsqu'un programme s'exécute sous sudo:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

Notez que ceux-ci peuvent être truqués simplement en les réglant. Ne leur faites pas confiance pour quoi que ce soit de critique.

Par exemple: Dans ce programme, nous devons dire à l'utilisateur d'exécuter un autre programme. Si celui en cours a été exécuté avec sudo, l'autre le sera aussi.

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

Notez qu'il ne teste une variable SUDO_ * que s'il peut d'abord prouver qu'elle s'exécute en tant que root. Même alors, il ne l'utilise que pour modifier du texte utile.

TomOnTime
la source
2
Que devrais-je utiliser pour «quelque chose de critique»?
Kevin - Rétablir Monica le
3
@Kevin, si quelqu'un se fout de son environnement pour simuler des privilèges élevés, il sait, espérons-le, ce qu'il fait et acceptera les conséquences.
Nick T
Voté parce que toute réponse qui doit être nuancée par «ne leur faites pas confiance pour quoi que ce soit de critique» n'est pas du tout une réponse, mais un vilain hack.
Stephen C
C'est une réponse parfaitement acceptable à la question qui a été posée. L'avertissement doit être là pour les personnes qui pourraient essayer d' empêcher l'utilisation de sudo, plutôt que de simplement le détecter . La prévention doit être effectuée à l'aide des alias de commande de sudo pour limiter les commandes que l'utilisateur peut exécuter.
dwurf
11

Cela ne répond pas directement à la question, mais je ne pense pas que la bonne question soit posée ici. Il me semble que le demandeur veut un programme qui agira vraisemblablement différemment s'il a certaines autorisations ou non, mais je dirais que la vérification de sudo n'est pas la façon de le faire. Premièrement, de nombreux systèmes peuvent ne pas implémenter un "sudo", ce n'est en aucun cas requis sous Linux ou de nombreux Unix.

Par exemple, un utilisateur peut déjà être connecté en tant que root, ce qui rend le sudo absurde ou peut-être que le système a des utilisateurs non root qui ont toujours les capacités d'effectuer la tâche administrative que le programme peut souhaiter effectuer. Enfin, peut-être que le système n'a pas de racine ou de sudo du tout et utilise à la place un système de contrôle d'accès obligatoire avec différentes capacités et aucun catch superutilisateur vers sudo. Ou l'utilisateur peut être créé, mais dans un compte qui a des autorisations -less- que son propre compte pour des raisons de sécurité (je lance souvent du code non approuvé avec un utilisateur temporaire non privilégié qui ne peut écrire sur des disques virtuels que pour supprimer, pas augmenter mes autorisations ). C'est globalement une mauvaise idée de supposer un modèle d'autorisations spécifique comme sudo ou l'existence de root ou de supposer qu'un utilisateur sudoed a des privilèges particuliers.

Si vous voulez savoir si vous avez les autorisations pour effectuer une opération, le meilleur moyen est généralement de simplement essayer de le faire, puis de vérifier errno pour les problèmes d'autorisations s'il échoue ou s'il s'agit d'une opération en plusieurs étapes qui doit soit échouer, soit réussir. vous pouvez vérifier si une opération fonctionnera avec des fonctions comme la fonction d' accès POSIX (méfiez-vous des conditions de concurrence possibles ici si les autorisations sont activement modifiées)

Si en plus vous avez besoin de connaître l'utilisateur réel derrière le sudo, vous pouvez utiliser la fonction getlogin qui devrait fonctionner pour toute session interactive avec un terminal sous-jacent et vous permettrait par exemple de trouver qui exécute `` réellement '' la commande pour l'audit ou de trouver le répertoire personnel de l'utilisateur réel pour enregistrer les journaux.

Enfin, si ce que vous voulez vraiment, c'est de savoir si un utilisateur a un accès root (toujours une mauvaise idée mais moins spécifique à l'implémentation), vous pouvez utiliser getuid pour vérifier un uid de 0 et donc root.

Vality
la source
7

Il existe deux mécanismes qui peuvent être utilisés.

  • La vérification des variables d'environnement peut être truquée dans les deux sens, mais c'est la plus simple à faire. growisofsn'aime pas fonctionner sous SUDO, donc je désactive les variables SUDO dans les scripts où je l'utilise. Il peut être truqué dans l'autre sens. (La variable SUDO est également transportée dans l'environnement pour les scripts exécutés sous les commandes at et batch.)
  • Une autre façon de voir si vous exécutez sous sudo est de parcourir la liste des processus depuis votre processus parent jusqu'à la recherche de sudo. Il serait difficile de cacher que vous exécutiez sous sudo de cette façon, mais c'est plus complexe. Il est toujours possible de simuler que vous exécutez sous sudo.

Il est plus courant de vérifier si vous utilisez en tant qu'utilisateur approprié. La idcommande peut être utilisée pour ce faire. Le script de TomOnTime utilise la idcommande pour déterminer s'il sudopeut être nécessaire d'exécuter la commande suivante.

BillThor
la source
1
> Il serait difficile de cacher que vous exécutiez sous sudo de cette façon. Ne pourriez-vous pas simplement renommer le sudobinaire en quelque chose d'autre? Ou nommer un autre exécutable sudopour simuler le contraire? Non pas que je m'attendrais vraiment à ce que quelqu'un d'esprit fasse ça ...
Bob
@Bob Vous auriez besoin d'un rootaccès pour renommer l' sudoexécutable. Un utilisateur normal ne serait pas en mesure de le faire. J'ai noté que vous pouvez simuler que vous courez sous sudo. Renommer un programme existant fonctionnerait. Le code requis pour un faux sudoprogramme dédié est trivial.
BillThor
vous pouvez simplement télécharger le binaire sudo quelque part et lui donner les bonnes autorisations ...
Jens Timmerman
@JensTimmerman Vous avez besoin d'un accès root pour lui donner les bonnes autorisations. Si vous pouvez simplement le renommer ou le lier en dur. Pas besoin de le télécharger. Si vous l'installez SUID sur un ID utilisateur cible (si cela fonctionnera de cette façon), vous devez avoir déjà compromis l'ID utilisateur cible.
BillThor
ah, c'est vrai, il refuse de travailler sans setuid, mon mauvais ...
Jens Timmerman
2

Vous pouvez comparer l'ID utilisateur effectif et réel.

Cela ne signifie pas strictement qu'il exécute undo sudo (pourrait également être défini), mais indique que le programme a plus de droits que l'utilisateur ne peut en attendre. (par exemple dans un programme qui est normalement exécuté sans ces droits, mais qui doit être exécuté avec eux lors de l'installation ou pour installer les mises à jour. Ensuite, vous pouvez l'utiliser pour donner des commentaires d'avertissement à ce sujet).

blabla999
la source
2
Non, sudodéfinit à la fois l'id effectif et réel. Par opposition à suid, qui ne fonctionne pas. Voici un programme C trivial que vous pouvez utiliser pour tester (désolé, le commentaire supprimera les nouvelles lignes, vous devrez les rajouter):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert
... ou, alternativement,perl -E 'say $<, "\n", $>'
derobert
2

Vous pouvez vérifier la variable UID (EUID) effective, comme suit:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi
Eliran Malka
la source
Cela ne répond pas à la question. Le code donne la même sortie lorsqu'il est exécuté en tant que root que lorsqu'il est exécuté en tant que sudo.
Stephen C
@StephenC - je pense qu'aux fins de l'OP, il n'y a pas de différence. À mon humble avis, leur objectif est d'identifier l'exécution sudo ou l'exécution à partir d'un shell racine authentique sans distinction.
Eliran Malka
1
Je pense que vous pourriez avoir raison. Je suis venu ici parce que je ne comprenais pas pourquoi sudo echo $USERimprime le nom d'utilisateur non privilégié (la variable est remplacée AVANT le sudo). En fait, j'ai fini par utiliser votre code dans mon script. Merci!
Stephen C
bienvenue :)
Eliran Malka
-1

Vous pouvez toucher un fichier /root, puis if -ele. Et si -e est vrai, rm(vérification du code d'erreur), votre test fonctionnera la prochaine fois.

La vérification du code d'erreur (ou du code retour) après la RM empêche quelqu'un d'utiliser facilement les pouvoirs sudo pour créer le fichier pour jouer une farce sur vous.

Chris K
la source
4
Cette réponse vérifie si le processus a la permission d'écrire /root(ce qui n'est pas nécessairement la même chose que l'exécution de l'UID 0), mais ne vérifie pas s'il a obtenu ces autorisations en utilisant sudo.
Ladadadada
Oui, les "mille façons d'écorcher un chat"; alors que j'écrivais la réponse, j'ai pensé à 4 ou 5 autres choses, alors je l'ai terminée.
Chris K
-2

J'ai trouvé que cela fonctionne bien pour cela

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]
ruckc
la source
Cela ne fonctionne pas lorsque je l'essaye sur FreeBSD, Centos7 ou MacOS X. Je pense que vous voulez dire "/ proc" au lieu de "/ etc". Mais même avec ce changement, cela ne fonctionne sur aucun de ces trois. "$ USER" est réinitialisé par sudo. Voulez-vous dire $ SUDO_USER? Aussi, vouliez-vous dire "[[" au lieu de "["?
TomOnTime du
1
j'ai corrigé l'exemple. Fondamentalement, la vérification de l'identifiant de connexion n'est pas égale à 0, mais l'utilisateur est root.
ruckc