Quello che è cambiato è che /bin/sh
entrambi sono diventati bash
o è rimasto dash
che ha ottenuto un flag aggiuntivo -p
imitando il comportamento di bash.
Bash richiede il -p
flag per non eliminare il privilegio setuid come spiegato nella sua pagina man:
Se la shell viene avviata con l'id effettivo dell'utente (gruppo) diverso dall'id reale dell'utente (gruppo) e l'opzione -p non viene fornita, non vengono letti file di avvio, le funzioni della shell non vengono ereditate dall'ambiente, SHELLOPTS, Le variabili BASHOPTS, CDPATH e GLOBIGNORE, se compaiono nell'ambiente, vengono ignorate, e l'ID utente effettivo viene impostato sull'ID utente reale . Se l'opzione -p viene fornita all'invocazione, il comportamento all'avvio è lo stesso, ma l'ID utente effettivo non viene reimpostato.
Prima, dash
non si è preoccupato di questo e ha permesso l'esecuzione di setuid (non facendo nulla per impedirlo). Ma il dash
di Ubuntu 16.04 La manpage di ha un'opzione aggiuntiva descritta, simile a bash
:
-p priv
Non tentare di reimpostare l'uid effettivo se non corrisponde all'uid. Questo non è impostato per impostazione predefinita per evitare un uso errato bysetuid programmi root tramite system(3) o popen(3).
Questa opzione non esisteva nell'upstream (che potrebbe non essere stato reattivo a una patch proposta) né in Debian 9 ma è presente in Debian buster che ha ricevuto la patch dal 2018.
NOTA:come spiegato da Stéphane Chazelas, è troppo tardi per invocare "/bin/sh -p"
in system()
perché system()
esegue qualsiasi cosa data attraverso /bin/sh
e quindi il setuid è già caduto. la risposta di derobert spiega come gestirlo, nel codice prima di system()
.
maggiori dettagli sulla cronologia qua e là.
Probabilmente la shell sta cambiando il suo ID utente effettivo nell'ID utente reale come parte del suo avvio per un motivo o per l'altro. Puoi 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 hai solo bisogno di impostare quelli veri; quelli salvati dovrebbero andare bene da soli. Questa è solo forza bruta per eseguire il debug. A seconda del motivo per cui sei set-id, potresti ovviamente aver bisogno per salvare anche gli ID reali 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. Ci sono molte variabili d'ambiente, per esempio, che influenzano il comportamento della shell. Preferisci un approccio già esistente come sudo
se possibile.]