Un programma può dire che viene eseguito su sudo?


27

Ho un programma che dovrebbe comportarsi diversamente se viene eseguito in "sudo". C'è un modo in cui può scoprire se è stato eseguito su sudo?

Aggiornamento: qualcuno ha chiesto perché dovrei voler fare questo. In questo caso, su un Mac che utilizza MacPorts c'è un output che ti dice di tagliare e incollare un comando particolare. Se il comando MacPorts è stato eseguito con "sudo", dovrebbe includere sudo nel comando di esempio:

$ 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 :-)

Sono curioso: puoi spiegare come dovrebbe comportarsi diversamente?
sciurus,

1
@sciurus di solito il caso d'uso comune è in uno script di installazione che richiede i privilegi di root; se non li hai, muori immediatamente.
Nick T,


Ricordo vagamente che qualche comando era consapevole che è eseguito come root o no ... Penso che la risposta sia "sì"
Rolf

Risposte:


48

Sì, ci sono 4 variabili d'ambiente impostate quando un programma è in esecuzione su sudo:

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

Si noti che questi possono essere falsificati semplicemente impostandoli. Non fidarti di loro per qualcosa di critico.

Ad esempio: in questo programma dobbiamo dire all'utente di eseguire qualche altro programma. Se quello attuale è stato eseguito con sudo, anche l'altro lo sarà.

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

Nota che verifica solo una variabile SUDO_ * se può prima provare che è in esecuzione come root. Anche allora lo usa solo per cambiare del testo utile.


2
Cosa dovrei usare per "qualcosa di critico?"
Kevin - Ripristina Monica il

3
@Kevin se qualcuno si rovina con il proprio ambiente per fingere di avere privilegi elevati, si spera che sappiano cosa stanno facendo e accetteranno le conseguenze.
Nick T,

Sottovalutato perché qualsiasi risposta che deve essere qualificata da "non fidarti di loro per qualcosa di critico" non è affatto una risposta, ma un brutto hack.
Stephen C,

Questa è una risposta perfettamente accettabile alla domanda che è stata posta. L'avvertimento deve essere lì per le persone che potrebbero tentare di prevenire l'uso di sudo, piuttosto che rilevarlo . La prevenzione deve essere eseguita utilizzando gli alias di comando di sudo per limitare i comandi che l'utente può eseguire.
Dwurf,

11

Questo non risponde direttamente alla domanda, ma non credo che la domanda giusta sia stata posta qui. Mi sembra che il richiedente richieda un programma che agirà in modo diverso presumibilmente se ha determinate autorizzazioni o meno, tuttavia direi che controllare sudo non è il modo di farlo. Innanzitutto molti sistemi potrebbero non implementare un "sudo", non è assolutamente necessario su Linux o su molti Unix.

Ad esempio, un utente può essere già registrato come root, rendendo il sudo privo di senso o forse il sistema ha utenti non root che hanno ancora capacità di eseguire l'attività amministrativa che il programma potrebbe voler fare. Infine, forse il sistema non ha alcun root o sudo e utilizza invece un sistema di controllo degli accessi obbligatorio con funzionalità diverse e non intercetta tutti i superutente sudo. Oppure l'utente potrebbe essere sottoposto a sudo, ma in un account che dispone di autorizzazioni senza licenza rispetto al proprio account per motivi di sicurezza (spesso eseguo codice non attendibile con un utente temporaneo senza privilegi che può solo scrivere su ramdisk per abbandonare, non aumentare le mie autorizzazioni ). Nel complesso è una cattiva idea assumere un modello di autorizzazioni specifico come sudo o l'esistenza di root o assumere che un utente sudoed abbia qualche privilegio particolare.

Se vuoi scoprire se disponi delle autorizzazioni per eseguire un'operazione, il modo migliore è di solito semplicemente provare a farlo, quindi controlla errno per problemi con le autorizzazioni se fallisce o se si tratta di un'operazione a più fasi che deve fallire o avere successo puoi verificare se un'operazione funzionerà con funzioni come la funzione di accesso POSIX (fai attenzione alle possibili condizioni di gara qui se i permessi vengono cambiati attivamente)

Se in aggiunta hai bisogno di conoscere l'utente reale dietro a sudo puoi usare la funzione getlogin che dovrebbe funzionare per qualsiasi sessione interattiva con un terminale sottostante e ti permetterebbe per esempio di trovare chi sta 'veramente' eseguendo il comando per il controllo o trovare il home directory dell'utente reale per salvare i registri.

Infine, se quello che vuoi davvero è scoprire se un utente ha accesso al root (ancora una cattiva idea ma meno specifica per l'implementazione) puoi usare getuid per controllare un uid di 0 e quindi root.


7

Esistono due meccanismi che possono essere utilizzati.

  • Il controllo delle variabili di ambiente può essere simulato in entrambi i modi, ma è il più semplice da fare. growisofsnon mi piace correre sotto SUDO, quindi ho disinserito le variabili SUDO negli script in cui lo uso. Può essere simulato in altro modo. (La variabile SUDO viene inoltre trasportata nell'ambiente per gli script eseguiti con i comandi at e batch.)
  • Un altro modo per vedere se si sta eseguendo sudo è quello di percorrere l'elenco dei processi dal proprio processo padre alla ricerca di sudo. Sarebbe difficile nascondere che stavi correndo sotto sudo in questo modo, ma è più complesso. È ancora possibile fingere che si stia eseguendo sudo.

È più comune verificare se si sta eseguendo l'utente appropriato. Il idcomando può essere usato per fare questo. Lo script di TomOnTime utilizza il idcomando per determinare se sudopotrebbe essere necessario eseguire il comando successivo.


1
> Sarebbe difficile nascondere che stavi eseguendo sudo in questo modo Non potresti semplicemente rinominare il sudobinario in qualcos'altro? O nominare un altro eseguibile sudoper simulare il contrario? Non che mi aspettassi davvero che qualcuno di sano lo facesse ...
Bob

@Bob Avresti bisogno rootdell'accesso per rinominare l' sudoeseguibile. Un utente normale non sarebbe in grado di farlo. Ho notato che puoi fingere che stai correndo sudo. Rinominare un programma esistente funzionerebbe. Il codice richiesto per un sudoprogramma falso dedicato è banale.
BillThor,

puoi semplicemente scaricare il binario sudo da qualche parte e dargli le giuste autorizzazioni ...
Jens Timmerman,

@JensTimmerman Hai bisogno dell'accesso root per dare le giuste autorizzazioni. Se puoi semplicemente rinominarlo o collegarlo al link. Non è necessario scaricarlo. Se lo installi SUID su un ID utente di destinazione (se funzionerà in questo modo), devi aver già compromesso l'ID utente di destinazione.
BillThor,

ah, giusto, si rifiuta di lavorare senza setuid, mio ​​cattivo ...
Jens Timmerman

2

È possibile confrontare l'ID utente effettivo con quello reale.

Ciò non significa strettamente che sia in esecuzione annulla sudo (potrebbe anche essere impostato), ma indica che il programma ha più diritti di quanto l'utente possa aspettarsi. (ad esempio in un programma che viene normalmente eseguito senza tali diritti, ma deve essere eseguito con essi durante l'installazione o per installare gli aggiornamenti. Quindi, è possibile utilizzare questo per fornire un feedback di avviso in merito).


2
No, sudoimposta sia l'ID effettivo che quello reale. Al contrario di suid, che non lo fa. Ecco un banale programma C che puoi usare per testare (scusami, il commento rimuoverà le nuove righe, dovrai aggiungerle di nuovo):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert

... o, in alternativa,perl -E 'say $<, "\n", $>'
derobert il

2

È possibile controllare la variabile UID (EUID) effettiva, come segue:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi

Questo non risponde alla domanda. Il codice fornisce lo stesso output quando viene eseguito come root come quando viene eseguito come sudo.
Stephen C,

@StephenC - penso che ai fini dell'OP non ci siano differenze. IMHO il loro obiettivo è identificare indifferentemente l'esecuzione o l'esecuzione di sudo da una shell root autentica.
Eliran Malka,

1
Penso che potresti avere ragione. Sono venuto qui perché non capivo perché sudo echo $USERstampa il nome utente non privilegiato (la variabile viene sostituita PRIMA del sudo). Ho finito per usare il tuo codice nel mio script. Grazie!
Stephen C,

molto gradito :)
Eliran Malka,

-1

È possibile toccare un file /roote quindi if -e. E se -e è vero, rm(controllando il codice di errore) in modo che il test funzioni la prossima volta.

Controllare il codice di errore (o il codice di ritorno) dopo che rm impedisce a qualcuno di usare facilmente i poteri sudo per creare il file per riprodurre uno scherzo su di te.


4
Questa risposta verifica se il processo dispone dell'autorizzazione per scrivere /root(che non è necessariamente uguale all'esecuzione di UID 0), ma non verifica se ha ottenuto tali autorizzazioni utilizzando sudo.
Ladadadada,

Sì, i "mille modi per scuoiare un gatto"; mentre scrivevo la risposta, ho pensato ad altre 4 o 5 cose, quindi l'ho finita.
Chris K,

-2

Ho scoperto che questo funziona bene per questo

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]

Questo non funziona quando lo provo su FreeBSD, Centos7 o MacOS X. Penso che intendi "/ proc" invece di "/ etc". Ma anche con quel cambiamento, non funziona su nessuno di questi tre. "$ USER" è resettato da sudo. Intendi $ SUDO_USER? Inoltre, intendevi "[[" anziché "["?
TomOnTime

1
ho risolto l'esempio. fondamentalmente controllando il loginuid non è uguale a 0, ma l'utente è root.
ruckc,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.