Kann ein Programm erkennen, dass es unter sudo ausgeführt wird?

27

Ich habe ein Programm, das sich anders verhalten sollte, wenn es unter "sudo" ausgeführt wird. Gibt es eine Möglichkeit herauszufinden, ob es unter sudo ausgeführt wurde?

Update: Jemand fragte, warum ich das tun möchte. In diesem Fall wird auf einem Mac mit MacPorts eine Ausgabe ausgegeben, in der Sie aufgefordert werden, einen bestimmten Befehl auszuschneiden und einzufügen. Wenn der MacPorts-Befehl mit "sudo" ausgeführt wurde, sollte sudo im Beispielbefehl enthalten sein:

$ 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
quelle
Ich bin neugierig: Kannst du erklären, wie es sich anders verhalten soll?
Sciurus
1
@sciurus ist normalerweise der häufigste Anwendungsfall in einem Installationsskript, für das Root-Berechtigungen erforderlich sind. Wenn du sie nicht hast, stirb einfach sofort.
Nick T
3
Das klingt nach meta.stackexchange.com/questions/66377/what-is-the-xy-problem/… . Was möchten Sie wirklich tun?
Jenny D sagt Reinstate Monica
Ich erinnere mich vage an einen Befehl, der wusste, dass er als root ausgeführt wird oder nicht ... Ich denke, die Antwort lautet "Ja"
Rolf

Antworten:

48

Ja, es sind 4 Umgebungsvariablen festgelegt, wenn ein Programm unter sudo ausgeführt wird:

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

Beachten Sie, dass diese gefälscht werden können, indem Sie sie einfach einstellen. Vertraue ihnen für nichts Kritisches.

Zum Beispiel: In diesem Programm müssen wir den Benutzer anweisen, ein anderes Programm auszuführen. Wenn der aktuelle mit sudo ausgeführt wurde, wird der andere ebenfalls ausgeführt.

#!/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

Beachten Sie, dass nur dann auf eine SUDO_ * -Variable geprüft wird, wenn zuerst nachgewiesen werden kann, dass sie als root ausgeführt wird. Selbst dann wird es nur zum Ändern von hilfreichem Text verwendet.

TomOnTime
quelle
2
Was würde ich für "irgendetwas Kritisches" verwenden?
Kevin - Reinstate Monica
3
@ Kevin, wenn sich jemand mit seiner Umgebung anstrengt, um zu fälschen, dass er über erhöhte Privilegien verfügt, dann weiß er hoffentlich, was er tut, und akzeptiert die Konsequenzen.
Nick T
Abgestimmt, weil jede Antwort, die mit "Vertraue ihnen nicht für etwas Kritisches" gekennzeichnet werden muss, überhaupt keine Antwort ist, sondern ein hässlicher Hack.
Stephen C
Dies ist eine völlig akzeptable Antwort auf die gestellte Frage. Die Warnung muss für Personen angezeigt werden, die versuchen, die Verwendung von sudo zu verhindern , anstatt es nur zu erkennen . Es sollte verhindert werden, dass sudos Befehls-Aliase verwendet werden, um zu begrenzen, welche Befehle der Benutzer ausführen kann.
Dwurf
11

Dies beantwortet die Frage nicht direkt, aber ich denke nicht, dass hier die richtige Frage gestellt wird. Mir scheint, der Fragesteller möchte ein Programm, das sich vermutlich anders verhält, wenn es bestimmte Berechtigungen hat oder nicht. Ich würde jedoch argumentieren, dass das Überprüfen auf sudo nicht der richtige Weg ist. Erstens können viele Systeme kein "sudo" implementieren, es ist auf keinen Fall unter Linux oder vielen Unixen erforderlich.

Beispielsweise ist ein Benutzer möglicherweise bereits als root angemeldet, was das sudo unsinnig macht, oder das System verfügt möglicherweise über Benutzer ohne Rootberechtigung, die weiterhin die vom Programm gewünschten Verwaltungsaufgaben ausführen können. Schließlich hat das System vielleicht überhaupt kein root oder sudo und verwendet stattdessen ein obligatorisches Zugriffskontrollsystem mit unterschiedlichen Fähigkeiten und keinen Zugriff auf alle Superuser, in die sudo soll. Oder der Benutzer kann sudoed werden, aber aus Sicherheitsgründen in ein Konto, das -less- Berechtigungen als sein eigenes Konto hat (Ich führe häufig nicht vertrauenswürdigen Code mit einem temporären nichtprivilegierten Benutzer aus, der nur auf RAM-Disks schreiben kann, um meine Berechtigungen zu löschen, nicht aber zu erhöhen ). Es ist insgesamt eine schlechte Idee, ein bestimmtes Berechtigungsmodell wie sudo oder das Vorhandensein von root anzunehmen oder anzunehmen, dass ein sudo-Benutzer über bestimmte Berechtigungen verfügt.

Wenn Sie herausfinden möchten, ob Sie über Berechtigungen zum Ausführen eines Vorgangs verfügen, versuchen Sie es in der Regel einfach und überprüfen Sie errno auf Berechtigungsprobleme, wenn der Vorgang fehlschlägt oder wenn es sich um einen mehrstufigen Vorgang handelt, bei dem entweder alle fehlschlagen oder alle erfolgreich sind Sie können überprüfen, ob eine Operation mit Funktionen wie der POSIX- Zugriffsfunktion funktioniert (achten Sie hier auf mögliche Rennbedingungen, wenn Berechtigungen aktiv geändert werden).

Wenn Sie zusätzlich den tatsächlichen Benutzer hinter dem sudo kennen müssen, können Sie die getlogin- Funktion verwenden, die für jede interaktive Sitzung mit einem zugrunde liegenden Terminal funktionieren sollte und es Ihnen beispielsweise ermöglichen würde, herauszufinden, wer den Befehl für die Prüfung „wirklich“ ausführt, oder die Funktion zu finden Ausgangsverzeichnis des realen Benutzers zum Speichern von Protokollen.

Wenn Sie wirklich herausfinden möchten, ob ein Benutzer über Root-Zugriff verfügt (immer noch eine schlechte Idee, aber weniger implementierungsspezifisch), können Sie getuid verwenden , um nach einer UID von 0 und damit root zu suchen.

Wertigkeit
quelle
7

Es gibt zwei Mechanismen, die verwendet werden können.

  • Das Überprüfen der Umgebungsvariablen kann auf beide Arten vorgetäuscht werden, ist jedoch am einfachsten. growisofsläuft nicht gerne unter SUDO, daher habe ich die SUDO-Variablen in Skripten, in denen ich sie verwende, deaktiviert. Es kann auch anders herum gefälscht werden. (Die SUDO-Variablen werden auch für Skripte in die Umgebung übertragen, die unter den Befehlen at und batch ausgeführt werden.)
  • Eine andere Möglichkeit, festzustellen, ob Sie unter sudo ausgeführt werden, besteht darin, die Prozessliste von Ihrem übergeordneten Prozess nach sudo zu durchsuchen. Es ist schwierig zu verbergen, dass Sie auf diese Weise unter sudo gelaufen sind, aber es ist komplexer. Es ist immer noch möglich zu behaupten, dass Sie unter sudo laufen.

Es ist üblicher, zu überprüfen, ob Sie als der entsprechende Benutzer ausgeführt werden. Der idBefehl kann dazu verwendet werden. Das Skript von TomOnTime verwendet den idBefehl, um festzustellen, ob sudomöglicherweise der nächste Befehl ausgeführt werden muss.

BillThor
quelle
1
> Es ist schwer zu verbergen, dass Sie auf diese Weise unter sudo gelaufen sind. Können Sie die sudoBinärdatei nicht einfach in etwas anderes umbenennen ? Oder nennen Sie eine andere ausführbare Datei sudo, um das Gegenteil vorzutäuschen? Nicht, dass ich wirklich erwarten würde, dass das jemand Vernünftiges tut ...
Bob
@ Bob Sie benötigen rootZugriff, um die sudoausführbare Datei umzubenennen . Ein normaler Benutzer wäre dazu nicht in der Lage. Ich habe bemerkt, dass Sie vortäuschen können, dass Sie unterlaufen sudo. Das Umbenennen eines vorhandenen Programms würde funktionieren. Der Code, der für ein spezielles Fake- sudoProgramm benötigt wird, ist trivial.
BillThor
Sie können einfach die Sudo-Binärdatei von irgendwo herunterladen und ihm die richtigen Berechtigungen geben ...
Jens Timmerman
@JensTimmerman Sie benötigen Root-Zugriff, um ihm die richtigen Berechtigungen zu erteilen. Wenn Sie es einfach umbenennen oder fest verknüpfen können. Es muss nicht heruntergeladen werden. Wenn Sie die SUID unter einer Zielbenutzer-ID installieren (sofern dies so funktioniert), müssen Sie die Zielbenutzer-ID bereits gefährdet haben.
BillThor
ah, richtig, es weigert sich, ohne setuid zu arbeiten, mein schlechtes ...
Jens Timmerman
2

Sie können die effektive mit der tatsächlichen Benutzer-ID vergleichen.

Dies bedeutet nicht unbedingt, dass es die Funktion "sudo rückgängig machen" ausführt (kann auch festgelegt werden), weist jedoch darauf hin, dass das Programm über mehr Rechte verfügt, als der Benutzer möglicherweise erwartet. (Zum Beispiel in einem Programm, das normalerweise ohne solche Rechte ausgeführt wird, aber während der Installation mit diesen ausgeführt werden muss oder um Updates zu installieren. Dann können Sie dies verwenden, um ein warnendes Feedback dazu zu geben.)

blabla999
quelle
2
Nein, sudosetzt sowohl die effektive als auch die reale ID. Im Gegensatz zu Suid, was nicht der Fall ist. Hier ist ein triviales C-Programm, mit dem Sie testen können (der Kommentar entfernt Zeilenumbrüche, Sie müssen sie wieder hinzufügen):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
Derobert
... oder alternativperl -E 'say $<, "\n", $>'
derobert
2

Sie können die effektive UID-Variable (EUID) wie folgt überprüfen:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi
Eliran Malka
quelle
Dies beantwortet die Frage nicht. Der Code gibt dieselbe Ausgabe aus, wenn er als root ausgeführt wird, wie wenn er als sudo ausgeführt wird.
Stephen C
@StephenC - Ich denke, für die Zwecke des OP gibt es keinen Unterschied. Meines Erachtens ist es ihr Ziel, die Sudo-Ausführung oder die Ausführung von einer authentischen Root-Shell ohne Unterscheidung zu identifizieren.
Eliran Malka
1
Ich denke, Sie könnten recht haben. Ich bin hierher gekommen, weil ich nicht verstanden habe, warum sudo echo $USERder nichtprivilegierte Benutzername ausgegeben wird (die Variable wird VOR dem Sudo ersetzt). Schließlich habe ich Ihren Code in meinem Skript verwendet. Vielen Dank!
Stephen C
herzlich willkommen :)
Eliran Malka
-1

Sie können eine Datei in /rootund dann berühren if -e. Und wenn -e wahr ist rm(Überprüfung des Fehlercodes), funktioniert der Test beim nächsten Mal.

Das Überprüfen des Fehlercodes (oder des Rückkehrcodes) nach dem rm verhindert, dass jemand die sudo powers verwendet, um die Datei zu erstellen, die Ihnen einen Streich spielt.

Chris K
quelle
4
Diese Antwort prüft, ob der Prozess über die Berechtigung zum Schreiben verfügt /root(was nicht unbedingt mit der Ausführung mit UID 0 identisch ist), prüft jedoch nicht, ob er über diese Berechtigungen verfügt sudo.
Ladadadada
Ja, die "tausend Wege, eine Katze zu häuten"; Als ich die Antwort schrieb, dachte ich an weitere 4 oder 5 Dinge, also packte ich sie ein.
Chris K
-2

Ich fand, dass dies gut dafür funktioniert

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]
ruckc
quelle
Dies funktioniert nicht, wenn ich es unter FreeBSD, Centos7 oder MacOS X versuche. Ich denke, Sie meinen "/ proc" anstelle von "/ etc". Aber selbst mit dieser Änderung funktioniert es bei keinem dieser drei. "$ USER" wird von sudo zurückgesetzt. Meinten Sie $ SUDO_USER? Meinten Sie auch "[[" statt "["?
TomOnTime
1
Ich habe das Beispiel repariert. Grundsätzlich ist das Prüfen auf die loginuid nicht gleich 0, aber der Benutzer ist root.
Ruckc