GNU/Linux >> Linux Esercitazione >  >> Linux

Consenti Setuid sugli script della shell?

Il setuid il bit di autorizzazione dice a Linux di eseguire un programma con l'ID utente effettivo del proprietario invece dell'esecutore:

> cat setuid-test.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv) {
    printf("%d", geteuid());
    return 0;
}

> gcc -o setuid-test setuid-test.c
> ./setuid-test

1000

> sudo chown nobody ./setuid-test; sudo chmod +s ./setuid-test
> ./setuid-test

65534

Tuttavia, questo si applica solo agli eseguibili; gli script di shell ignorano il bit setuid:

> cat setuid-test2

#!/bin/bash
id -u

> ./setuid-test2

1000

> sudo chown nobody ./setuid-test2; sudo chmod +s ./setuid-test2
> ./setuid-test2

1000

Wikipedia dice:

A causa della maggiore probabilità di falle di sicurezza, molti sistemi operativi ignorano l'attributo setuid quando applicato a script di shell eseguibili.

Supponendo che io sia disposto ad accettare questi rischi, c'è un modo per dire a Linux di trattare il bit setuid allo stesso modo degli script di shell come fa sugli eseguibili?

In caso negativo, esiste una soluzione comune per questo problema? La mia soluzione attuale è aggiungere un sudoers per consentire ALL per eseguire un determinato script come utente che voglio che venga eseguito, con NOPASSWD per evitare la richiesta della password. Il principale svantaggio è la necessità di un sudoers voce ogni volta che voglio farlo e la necessità per il chiamante di sudo some-script invece di solo some-script

Risposta accettata:

Linux ignora il bit setuid¹ su tutti gli eseguibili interpretati (cioè gli eseguibili che iniziano con un #! linea). Le FAQ di comp.unix.questions spiegano i problemi di sicurezza con gli script di shell setuid. Questi problemi sono di due tipi:relativi a shebang e relativi alle conchiglie; Entro in maggiori dettagli di seguito.

Se non ti interessa la sicurezza e vuoi consentire gli script setuid, sotto Linux, dovrai patchare il kernel. A partire dai kernel 3.x, penso che tu debba aggiungere una chiamata a install_exec_creds nel load_script funzione, prima della chiamata a open_exec , ma non ho provato.

Setuid Shebang

Esiste una condizione di razza inerente al modo in cui shebang (#! ) è in genere implementato:

  1. Il kernel apre l'eseguibile e scopre che inizia con #! .
  2. Il kernel chiude l'eseguibile e apre invece l'interprete.
  3. Il kernel inserisce il percorso dello script nell'elenco degli argomenti (come argv[1] ), ed esegue l'interprete.

Se gli script setuid sono consentiti con questa implementazione, un utente malintenzionato può invocare uno script arbitrario creando un collegamento simbolico a uno script setuid esistente, eseguendolo e organizzando la modifica del collegamento dopo che il kernel ha eseguito il passaggio 1 e prima che l'interprete riesca a aprendo il suo primo argomento. Per questo motivo, la maggior parte degli unice ignora il bit setuid quando rilevano uno shebang.

Un modo per proteggere questa implementazione sarebbe che il kernel blocchi il file di script fino a quando l'interprete non lo ha aperto (notare che questo deve impedire non solo di scollegare o sovrascrivere il file, ma anche di rinominare qualsiasi directory nel percorso). Ma i sistemi Unix tendono a evitare i blocchi obbligatori e i collegamenti simbolici renderebbero una funzione di blocco corretta particolarmente difficile e invasiva. Penso che nessuno lo faccia in questo modo.

Alcuni sistemi Unix (principalmente OpenBSD, NetBSD e Mac OS X, che richiedono tutti l'abilitazione di un'impostazione del kernel) implementano setuid shebang utilizzando una funzionalità aggiuntiva:il percorso /dev/fd/N fa riferimento al file già aperto nel descrittore di file N (quindi aprendo /dev/fd/N è più o meno equivalente a dup(N) ). Molti sistemi Unix (incluso Linux) hanno /dev/fd ma non script setuidi.

  1. Il kernel apre l'eseguibile e scopre che inizia con #! . Diciamo che il descrittore di file per l'eseguibile è 3.
  2. Il kernel apre l'interprete.
  3. Il kernel inserisce /dev/fd/3 l'elenco degli argomenti (come argv[1] ), ed esegue l'interprete.
Correlati:quali sono i parametri/variabili speciali della shell (Bash)?

Pagina shebang di Sven Mascheck ha molte informazioni su shebang negli unice, incluso il supporto a setuid.

Interpreti Setuidi

Supponiamo che tu sia riuscito a far funzionare il tuo programma come root, o perché il tuo sistema operativo supporta setuid shebang o perché hai usato un wrapper binario nativo (come sudo ). Hai aperto un buco di sicurezza? Forse . Il problema qui è non sui programmi interpretati rispetto a quelli compilati. Il problema è se il tuo sistema di runtime si comporta in modo sicuro se eseguito con privilegi.

  • Qualsiasi eseguibile binario nativo collegato dinamicamente viene in qualche modo interpretato dal caricatore dinamico (es. /lib/ld.so ), che carica le librerie dinamiche richieste dal programma. Su molti Unice, puoi configurare il percorso di ricerca per le librerie dinamiche attraverso l'ambiente (LD_LIBRARY_PATH è un nome comune per la variabile di ambiente) e carica anche librerie aggiuntive in tutti i binari eseguiti (LD_PRELOAD ). L'invocatore del programma può eseguire codice arbitrario nel contesto di quel programma inserendo un libc.so appositamente predisposto in $LD_LIBRARY_PATH (tra le altre tattiche). Tutti i sistemi sani ignorano il LD_* variabili negli eseguibili setuid.

  • In conchiglie come sh, csh e derivati, le variabili d'ambiente diventano automaticamente parametri della shell. Attraverso parametri come PATH , IFS e molti altri, l'invocatore dello script ha molte opportunità per eseguire codice arbitrario nel contesto degli script della shell. Alcune shell impostano queste variabili su valori predefiniti sani se rilevano che lo script è stato invocato con privilegi, ma non so se esiste un'implementazione particolare di cui mi fido.

  • La maggior parte degli ambienti di runtime (sia nativo, bytecode o interpretato) hanno caratteristiche simili. Pochi prendono precauzioni speciali negli eseguibili setuid, anche se quelli che eseguono codice nativo spesso non fanno nulla di più elaborato del collegamento dinamico (che prende precauzioni).

  • Perl è una notevole eccezione. Supporta esplicitamente gli script setuid in modo sicuro. In effetti, il tuo script può eseguire setuid anche se il tuo sistema operativo ha ignorato il bit setuid sugli script. Questo perché perl viene fornito con un root helper setuid che esegue i controlli necessari e richiama nuovamente l'interprete sugli script desiderati con i privilegi desiderati. Questo è spiegato nel manuale di perlsec. Una volta gli script perl setuid avevano bisogno di #!/usr/bin/suidperl -wT invece di #!/usr/bin/perl -wT , ma sulla maggior parte dei sistemi moderni, #!/usr/bin/perl -wT è sufficiente.

Tieni presente che l'utilizzo di un wrapper binario nativo non fa nulla di per sé per prevenire questi problemi . In effetti, può rendere la situazione peggiora , perché potrebbe impedire al tuo ambiente di runtime di rilevare che è stato invocato con privilegi e di ignorare la sua configurabilità di runtime.

Un wrapper binario nativo può rendere sicuro uno script di shell se il wrapper disinfetta l'ambiente . Lo script deve fare attenzione a non fare troppe ipotesi (ad esempio sulla directory corrente), ma questo va bene. Puoi usare sudo per questo a condizione che sia impostato per igienizzare l'ambiente. Le variabili nella lista nera sono soggette a errori, quindi sempre nella lista bianca. Con sudo, assicurati che env_reset opzione è attivata, quel setenv è disattivato e quel env_file e env_keep contengono solo variabili innocue.

Correlati:come sfuggire alle virgolette nella shell?

TL,DR:

  • Setuid Shebang è insicuro ma di solito viene ignorato.
  • Se esegui un programma con privilegi (tramite sudo o setuid), scrivi codice nativo o perl, oppure avvia il programma con un wrapper che sanifica l'ambiente (come sudo con env_reset opzione).

¹ Questa discussione vale ugualmente se sostituisci “setgid” con “setuid”; sono entrambi ignorati dal kernel Linux sugli script


Linux
  1. Nascondere la password negli script della shell?

  2. Estensioni di file per script di shell Unix?

  3. Condivisione di variabili su più script di shell?

  4. Come verificare la conformità a Posix degli script della shell?

  5. Esegui tutti gli script della shell nella cartella

Come creare script di shell

Array negli script di shell

Come utilizzare if-else negli script della shell?

Comprendere il ciclo for negli script della shell

Il ciclo while negli script della shell

Perché SUID è disabilitato per gli script di shell ma non per i file binari?