Se aggiungi il bit setuid per il permesso di un file in cui hai il permesso di esecuzione, cambia il x
a un s
significa che se esegui quel file, verrà eseguito come proprietario del file anziché come persona che lo esegue effettivamente.
Ma ho anche notato che se aggiungi s
permesso ma rimuovi x
permesso cambia in una S
nell'elenco delle autorizzazioni. In qualche modo questo implicherebbe che non potrebbe essere eseguito ma sarebbe simultaneamente eseguito come proprietario se potesse essere eseguito? È vero?
Sto fraintendendo questo permesso? A cosa serve? Cosa significa?
Risposta accettata:
Tutte e quattro le combinazioni esistono e sono significative.
"Il proprietario effettivo di questo file può eseguirlo?" e "Chi pretenderà che il sistema stia eseguendo questo file?" sono due domande separate Tutte e quattro le combinazioni sono possibili e significative.
Stringhe di autorizzazione visualizzate da ls -l
o stat -c %A
show, nella posizione di esecuzione del proprietario (cioè, al posto di ?
in ---?------
), quattro caratteri diversi, uno per ogni combinazione:
-
significa che il proprietario non può esegui il file e, se un non proprietario lo esegue, viene eseguito come quell'altro utente .x
significa che il proprietario può esegui il file e, se un non proprietario lo esegue, viene eseguito come quell'altro utente .S
significa che il proprietario non può esegui il file e, se lo esegue un non proprietario, viene eseguito come proprietario .s
significa che il proprietario può esegui il file e, se lo esegue un non proprietario, viene eseguito come proprietario .
Il bit setuid ei bit di esecuzione sono bit separati e la modalità stringa è davvero solo un modo conveniente per visualizzare i bit di autorizzazione, compresi quelli. Un altro modo per pensarci è:
x
os
significa che il bit di esecuzione è impostato.-
oS
significa che non lo è.s
oS
significa che il bit setuid è impostato.-
ox
significa che non lo è.
Allo stesso modo, un gruppo può avere o meno autorizzazioni di esecuzione su un file e, se eseguito, può essere eseguito o meno con un'identità di gruppo diversa da quella dell'utente che lo esegue. Per fare in modo che un file venga eseguito con l'identità del gruppo del suo proprietario piuttosto che con quella dell'utente che lo esegue, devi impostare il bit setgid (------s---
o ------S---
).
S
non rappresenta un bit di modalità separato. È semplicemente un modo per indicare che il bit setuid (o setgid) è impostato ma il bit eseguibile corrispondente non è impostato.
$ touch foo
$ chmod u+S foo
chmod: invalid mode: ‘u+S’
Try 'chmod --help' for more information.
Puoi esaminare i bit stessi.
Per vedere che questi sono bit separati, usa il %a
identificatore di formato per stat
invece di %A
. Per semplificare le cose, ho disattivato tutti gli altri bit di modalità.
$ touch a b c d
$ chmod u=,g=,o= a
$ chmod u=x,g=,o= b
$ chmod u=s,g=,o= c
$ chmod u=xs,g=,o= d
$ stat -c '%A %n' a b c d
---------- a
---x------ b
---S------ c
---s------ d
$ stat -c '%04a %n' a b c d
0000 a
0100 b
4000 c
4100 d
Questo chiarisce... se sei a tuo agio con l'ottale. Se vuoi vederlo in binario (loro sono bit dopo tutto) puoi convertire le rappresentazioni:
$ stat -c '%a %n' a b c d | perl -pe 's/\d+/sprintf("%012b", oct($&))/e'
000000000000 a
000001000000 b
100000000000 c
100001000000 d
Setuid imposta l'ID utente effettivo, non l'ID utente reale.
I bit di esecuzione controllano se un tentativo di eseguire un file può avere successo o meno, mentre i bit setuid/setgid controllano la cui identità viene eseguito il nuovo processo se è consentito crearlo. Quindi non c'è nulla di incoerente o sorprendente nella combinazione dei permessi S
rappresenta (-x,+s
). Questo sarebbe così anche se un eseguibile in esecuzione come proprietario perché il suo proprietario lo ha davvero eseguito, funzionasse esattamente come un eseguibile in esecuzione come proprietario perché qualcuno lo ha eseguito ma era setuid. Ma non è così che funziona.
Il kernel utilizza più di un numero per tenere traccia dell'identità dell'utente di un processo in esecuzione. Uno di questi numeri è l'UID e un altro è l'EUID. Vedi questo articolo per i dettagli. Il bit setuid determina la modifica dell'EUID (ID utente effettivo), ma l'UID (ID utente reale) rimane lo stesso. Un uso di questo per consentire lo scambio di segnali tra processi che condividono un UID ma hanno EUID diversi, ma un altro è che consente a un programma progettato per avere il bit setuid impostato per controllare chi lo ha eseguito .
Ad esempio, passwd
deve essere setuid, perché solo root può modificare le voci nel database delle password:
$ ls -l "$(command -v passwd)"
-rwsr-xr-x 1 root root 54256 May 16 19:37 /usr/bin/passwd
-rwsr-xr-x
ha r-x
alla fine, per altri . A causa della x
, anche gli utenti che non sono root o nel gruppo root possono eseguire passwd
. E ha rws
vicino all'inizio, per il proprietario . A causa dei s
, il programma viene eseguito come root, anche quando non lo eseguono i proprietari. Ma quando esegui passwd
te stesso, reimposta la tua password, non quella di root.
passwd
è capace di eseguire qualsiasi modifica al database di utenti e password, perché viene eseguito con l'ID utente effettivo di root. Ma è progettato per rifiutarsi di modificare la password di chiunque tranne l'utente l'ha eseguita, tranne quando quell'utente è root, perché controlla il suo vero ID utente.
Questo è il tipico caso d'uso dell'eseguibile setuid:creare un'interfaccia che consenta a un utente di far eseguire azioni come un altro, in un modo limitato che è controllato dal codice dell'eseguibile setuid. Quindi è sicuro solo impostare il bit setuid (o il bit setgid) su un programma progettato per avere quei permessi.
Questo è l'altro pezzo del puzzle per capire perché i permessi S
significa che non sono enigma:il potere conferito dal bit setuid non ottenere lo stesso risultato di eseguire effettivamente il programma come il suo proprietario , anche dopo che il programma è stato autorizzato a essere eseguito.
Controllo di UID e EUID con una copia di id
mostra come funziona setuid.
Ok, bene, imposterò il bit setuid su un eseguibile che non è progettato per questo, per mostrare come vengono influenzati gli ID utente reali ed effettivi.
- L'eseguibile sarà una copia dell'
id
programma che, tra l'altro, riporta i suoi ID utente reali ed effettivi. Sebbene questo programma non sia progettato per essere setuito, non è nemmeno progettato per cambiare nulla, tranne che producendo output, quindi è ragionevolmente sicuro. Ma dovresti comunque eliminarlo in seguito. (La tua copia. Non l'originale.) - Stiamo utilizzando una copia, non modifica dei permessi sull'originale. Tu non devi usare
sudo
o esegui qualsiasi azione come root per questo. - Per eseguirlo come un altro utente, è necessario un secondo account utente, ma puoi utilizzare
su
per eseguire azioni come quello utente. (Per impostazione predefinita, ilroot
l'account non ti consente di accedere in quanto con una password, quindi se commetti un errore ed eseguisu
senza fornire il nome utente a cui vuoi passare, non finirai invece per diventare accidentalmente root, a meno che tu non abbia abilitato anche i login di root. Se vuoi davvero usaresudo -u user
invece disu user -c
, però, allora puoi.)
Il mio account utente principale si chiama ek
e il mio secondo account è ek2
. Va bene se i tuoi sono diversi. Innanzitutto, come ek
, copio id
alla directory corrente (che è da qualche parte all'interno della mia home directory):
$ type -a id
id is /usr/bin/id
$ cp /usr/bin/id .
La copia ha la proprietà dell'utente non root che l'ha copiata, ma i permessi originali:
$ ls -l id /usr/bin/id
-rwxr-xr-x 1 ek ek 39760 Oct 5 11:23 id
-rwxr-xr-x 1 root root 39760 Mar 2 2017 /usr/bin/id
Passando -n
a id
mostra i nomi invece dei numeri ID, -u
mostra l'utente (e non altre informazioni come i gruppi) e -r
fa sì che venga mostrato l'ID utente reale. Senza -r
, -u
mostra l'ID utente effettivo. Questo comportamento si applica completamente alla copia di id
l'ho appena fatto.
Quando lo eseguo come utente sostitutivo, gli ID utente reali ed effettivi vengono entrambi modificati. Questo fa parte di come su
e sudo
sono scritti, e non è un semplice risultato di su
essendo esso stesso radice setuide, sebbene lo sia. (Questo è il motivo per cui ho usato passwd
come esempio di un tipico eseguibile setuid, piuttosto che su
o sudo
.) Questa è la nostra linea di base, per vedere quel id
nella directory corrente funziona come previsto:
$ ./id -nu # ek runs id, displaying the effective user
ek
$ ./id -nur # ek runs id, displaying the real user
ek
$ su ek2 -c './id -nu' # ek2 runs id, displaying the effective user
Password:
ek2
$ su ek2 -c './id -nur' # ek2 runs id, displaying the real user
Password:
ek2
Ora faccio questa copia locale di id
setuid:
$ chmod u+s id
$ ls -l id
-rwsr-xr-x 1 ek ek 39760 Oct 5 11:42 id
Ora, quando lo eseguo, il suo vero ID utente è ancora quello dell'utente che lo ha eseguito, mentre il suo effettivo ID utente è quello di ek
anche quando ek2
lo esegue:
$ ./id -nu # ek runs id, displaying the effective user
ek
$ ./id -nur # ek runs id, displaying the real user
ek
$ su ek2 -c './id -nu' # ek2 runs id, displaying the effective user
Password:
ek
$ su ek2 -c './id -nur' # ek2 runs id, displaying the real user
Password:
ek2
Ora tolgo le autorizzazioni eseguibili al proprietario ma le lascio per tutti gli altri:
$ chmod u-x id
$ ls -l id
-rwSr-xr-x 1 ek ek 39760 Oct 5 11:42 id
ek2
può ancora eseguirlo come con ek
è l'ID utente effettivo, anche se ek
impossibile eseguirlo:
$ ./id -nu # ek runs id, displaying the effective user
-bash: ./id: Permission denied
$ ./id -nur # ek runs id, displaying the real user
-bash: ./id: Permission denied
$ su ek2 -c './id -nu' # ek2 runs id, displaying the effective user
Password:
ek
$ su ek2 -c './id -nur' # ek2 runs id, displaying the real user
Password:
ek2
Ma, come mostrato, questo non ha prodotto lo stesso risultato di ek
effettivamente eseguirlo. ek2
non posso davvero fare ciò che ek
potrebbe fare se ek
sono stati autorizzati a eseguire il programma, a meno che il programma non lo consenta.
(In seguito, ho eseguito rm id
per rimuovere il file, quindi non avrei un eseguibile setuid non necessario in giro nella mia home directory. Oppure potresti semplicemente deselezionare il bit setuid con chmod -s id
.)