Perché il bit setuid funziona in modo incoerente?


8

Ho scritto il codice:

// a.c
#include <stdlib.h>
int main () {
  system("/bin/sh");
  return 0;
}

compilato con il comando:

gcc a.c -o a.out

aggiunto bit setuid su di esso:

sudo chown root.root a.out
sudo chmod 4755 a.out

Su Ubuntu 14.04, quando corro come utente generico, ho ottenuto il privilegio di root.

ma su Ubuntu 16.04, ho ancora la shell dell'utente corrente.

Perché è diverso?

Risposte:


9

Ciò che è cambiato è che è /bin/shdiventato basho è rimasto dashche ha ottenuto una bandiera aggiuntiva che -pimita il comportamento di Bash.

Bash richiede che il -pflag non rilasci il privilegio setuid come spiegato nella sua pagina man :

Se la shell viene avviata con l'ID utente (gruppo) effettivo non uguale all'id utente (gruppo) reale e l'opzione -p non viene fornita, non viene letto alcun file di avvio, le funzioni della shell non vengono ereditate dall'ambiente, SHELLOPTS , Le variabili BASHOPTS, CDPATH e GLOBIGNORE, se visualizzate nell'ambiente, vengono ignorate e l'ID utente effettivo viene impostato sull'ID utente reale . Se l'opzione -p viene fornita al momento dell'invocazione, il comportamento all'avvio è lo stesso, ma l'id utente effettivo non viene ripristinato.

Prima dashnon gliene importava nulla e consentiva l'esecuzione di setuid (non facendo nulla per impedirlo). Ma la dashmanpage di Ubuntu 16.04 ha un'opzione aggiuntiva descritta, simile a bash:

-p priv
Non tentare di ripristinare l'UID efficace se non corrisponde all'UID. Questo non è impostato di default per evitare un uso errato da parte dei programmi root setuid tramite system (3) o popen (3).

Questa opzione non esisteva in upstream (che potrebbe non essere stata reattiva a una patch proposta * ) né in Debian 9 ma è presente in Debian buster che ha ottenuto la patch dal 2018.

NOTA: come spiegato da Stéphane Chazelas, è troppo tardi per invocare "/bin/sh -p"in system()quanto system()corre qualche cosa data per mezzo /bin/she così il setuid è già caduto. La risposta di derobert spiega come gestirlo, nel codice precedente system().

* maggiori dettagli sulla storia qua e .


system("bash -p")viene eseguito in sh -c "bash -p"modo che i privilegi siano già stati eliminati quando bashviene eseguito.
Stéphane Chazelas,

vabbè ok Rimuoverò comunque la parte "soluzione" meglio gestita dalla risposta di Derobert.
AB


Sembra Ubuntu con trattino fisso in astuto (15.10). bugs.launchpad.net/ubuntu/+source/dash/+bug/1215660
Mark Plotnick

1
Nota che Debian faceva il contrario. Era solito patchare bash in modo da non eliminare i privilegi. È discutibile se si tratti di un miglioramento. Ora, le persone che vogliono fare un system()privilegio elevato (che, garantito, non dovrebbero in primo luogo) finiscono per fare un setresuid()precedente che è molto peggio, dato che la shell non sa che è suid, quindi no attivare la modalità in cui non si fida del proprio ambiente.
Stéphane Chazelas,

8

Probabilmente la shell sta cambiando il suo ID utente effettivo in quello reale come parte del suo avvio per qualche motivo o altro. È possibile verificarlo aggiungendo:

/* needs _GNU_SOURCE; non-Linux users see setregid/setreuid instead */
uid_t euid = geteuid(), egid = getegid();
setresgid(egid, egid, egid);
setresuid(euid, euid, euid);

prima del tuo system(). (In realtà, anche su Linux, probabilmente devi solo impostare quelli reali; quelli salvati dovrebbero andare bene da soli. Questa è solo una forza bruta per il debug. A seconda del motivo per cui sei set-id, potresti ovviamente aver bisogno per salvare gli ID reali anche da qualche parte.)

[Inoltre, se questo non è solo un esercizio per imparare come funziona setid, allora ci sono molti problemi di sicurezza di cui preoccuparsi, specialmente quando si chiama una shell. Esistono molte variabili di ambiente, ad esempio, che influenzano il comportamento della shell. Preferisci un approccio già esistente come sudose fosse possibile.]


Mi sono concentrato sul perché è cambiato, mentre tu mi hai fornito il modo per evitare il problema. +1
AB

Naturalmente, se hai davvero bisogno di un posto per salvare i veri ID, l'ID salvato è un posto terribilmente conveniente per farlo. Soprattutto se gli ID effettivi non sono root: root.
Kevin,
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.