Chiamare uno script da un programma setuid radice C - script non viene eseguito come root
Domanda
Ho bisogno di eseguire uno script bash come root (senza password sudo o su non vitali) e dal momento che non è possibile setuid uno script in Linux, ho pensato di chiamare da un eseguibile e fare è setuid:
$ cat wrapper.c
int main(void)
{
system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ sudo chown root wrapper
$ sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$
Questo funziona - come nel eseguito correttamente lo script -. Ma lo script viene eseguito come l'utente che esegue "./wrapper"
Perché? E come implementare correttamente questo?
Grazie!
Soluzione
Dato che il bit suid
su eseguibili cambia solo l'effettivo UID (EUID) l'eseguibile verrà eseguito come, e non il vero UID (RUID), che getuid()
ritorni, e in aggiunta alla limitazione suid
interpretato script (ogni inizio eseguibile "#!
"), alcune conchiglie come bash
come misura di sicurezza in più imposterà l'EUID indietro al RUID in questo caso, sarà necessario utilizzare il setuid(0)
chiamata nel codice C prima di eseguire lo script.
Si vedano le pagine man
del setuid
, seteuid
, getuid
, e geteuid
di apprendere la semantica esatte dei UID reale ed efficace.
( ATTENZIONE ) Naturalmente, questo è un punto opportuno ricordare che la restrizione sugli script suid
In molti sistemi Unix, conchiglie e interpreti, ci sono per un motivo, che è che se lo script non è molto attento a sanificazione suo ingresso e lo stato dell'ambiente quando viene eseguita, sono pericolosi e possono essere sfruttati per l'escalation di sicurezza. Quindi, essere molto attenti quando si fa questo. Impostare l'accesso allo script e involucro altrettanto rigorose come si può, consentire solo questo script molto specifico che si intende eseguire, e di chiarire l'ambiente all'interno del programma C prima di avviare lo script, delle variabili di ambiente come PATH
da contenere esattamente ciò che è necessaria nel giusto ordine e nessuna directory che sono scrivibili ad altri.
Altri suggerimenti
Un'altra cosa da notare qui è che la limitazione qui è da bash e non il sistema * nix stesso. Bash effettivamente fare verifiche su script SUID a loro eseguire solo con la radice EUID. Se si prende conchiglie più anziani, spesso è possibile ottenere ciò che si voleva fuori dalla scatola. Ad esempio, sh non fa questo tipo di verifiche:
$ cat wrapper.c
int main(void)
{
system("/bin/sh -c whoami");
}
$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:15 wrapper
$ ./wrapper
root
Con bash:
$ cat wrapper.c
int main(void)
{
system("/bin/bash -c whoami");
}
$ ls -l wrapper
-rwsr-sr-x 1 root users 8887 Feb 17 14:18 wrapper
$ ./wrapper
skinp
Ancora, la risposta di Tom è in genere la strada da percorrere per fare un wrapper per i programmi di root SUID
Aggiungere il setuid (0) nello script e compilarlo. Dovrebbe funzionare dopo questo.
$ cat wrapper.c
int main(void)
{
setuid(0);
system("/bin/bash ./should_run_as_root.sh");
}
$ gcc -o wrapper wrapper.c
$ sudo chown root wrapper
$ sudo chmod ug+s wrapper
$ ll wrapper
-rwsr-sr-x 1 root users 6667 2009-02-17 11:11 wrapper
$
Gli esempi sono terribilmente insicuro e consente a chiunque con due bit di conoscenza per eseguire qualsiasi programma che vogliono come l'utente setuid.
Non passare attraverso una shell a meno che non sanificare l'ambiente prima, la maggior parte degli esempi mostrati qui sono vulnerabili ad avere IFS e percorso impostato prima di eseguirlo.
Perché non è sudo praticabile? Evita infuria buchi di sicurezza come ad esempio:
bash-3.2$ cat test
#!/bin/bash
echo ima shell script durp durp
bash-3.2$ chmod +x test
bash-3.2$ ./test
heh heh
bash-3.2$
A causa dell'ambiente non essere adeguatamente sterilizzate, ad esempio in questo caso:
export echo='() { builtin echo heh heh; }'
sudo disinfetta questo caso, e forse altri casi limite e trucchi che sarebbe bene a non scrivere in un involucro suid personalizzato.