Cosa significa setresuid() e setresgid() fare?
Per comprendere meglio questo esempio, dobbiamo dare un'occhiata a queste due funzioni e ai tre parametri che accettano.
Da questa risposta (e dalla pagina man delle credenziali(7):
Su Linux, ogni processo ha i seguenti identificatori di utenti e gruppi:
ID utente reale e ID gruppo reale. Questi ID determinano chi possiede il processo. Per riassumere, questo è chi sei .
ID utente effettivo e ID gruppo effettivo. Questi ID vengono utilizzati dal kernel per determinare le autorizzazioni che il processo avrà quando accede a risorse condivise come code di messaggi, memoria condivisa e semafori. Sulla maggior parte dei sistemi UNIX, questi ID determinano anche le autorizzazioni per l'accesso ai file. Tuttavia, Linux utilizza gli ID del file system per questa attività. Per riassumere, questo è quello che puoi fare .
Set-user-ID salvato e set-group-ID salvato. Questi ID vengono utilizzati nei programmi set-user-ID e set-group-ID per salvare una copia degli ID effettivi corrispondenti impostati quando il programma è stato eseguito. Un programma set-user-ID può assumere e abbandonare i privilegi scambiando il proprio ID utente effettivo avanti e indietro tra i valori nel suo ID utente reale e l'ID set-utente salvato. Per riassumere, questo è quello che eri prima .
Inoltre, è importante comprendere il bit SetUID. Ciò che fa è eseguire un programma eseguibile con i diritti del proprietario, non di colui che lo chiama.
Un nightmare di sicurezza
La tua domanda menziona specificamente quel nightmare è di proprietà di root e ha il SetUID-Bit impostato. Ciò significa che qualsiasi utente a cui è consentito eseguire nightmare essenzialmente lo esegue come root . Ciò significa che tutti i processi figli di nightmare - come quelli generati quando si chiama system() - vengono eseguiti anche come root .
Ma davvero ora, cosa significa setresuid() fare?
In tale contesto? Niente. Poiché l'utente sta già eseguendo cose come root , non influisce in alcun modo sull'ulteriore sfruttamento.
Potresti usare /dev/tty ?
Questa domanda non ha molto senso in questo contesto. Devi guardare lo snippet di codice pertinente per vedere dove si trova la stringa /dev/tty viene da.
if (open("/dev/tty", O_RDWR) != -1) {
fire();
rax = sub_4008d0();
}
Ciò significa che il programma sta tentando di aprire /dev/tty per leggere e scrivere e se ciò riesce, chiama fire() .
Denominando una funzione bash /dev/tty() , non ottieni i risultati desiderati, come open() richiede il percorso di un file come primo parametro. È completamente indipendente da bash e non ha il concetto di funzioni bash.
Che ne dici di puts() ?
Allo stesso modo, questo non ha molto senso. strings non è una magia e non capisce il contesto. Tutto ciò che fa è cercare una serie di byte che siano caratteri ASCII stampabili.
puts() è solo una funzione C che emette una stringa.
Che ne dici di /usr/bin/aafire ?
Anche se non l'ho provato personalmente, sembra praticamente /usr/bin/aafire avrebbe potuto essere usato al posto di /usr/bin/sl -al . Se questo non è corretto, per favore commenta e modificherò questa parte.
Funzionerebbe ancora se venisse utilizzato un percorso relativo?
Sì, in realtà anche meglio! system() chiama internamente sh -c , che deve risolvere il $PATH variabile per trovare sl . Se la variabile del percorso è stata modificata per includere . o qualsiasi altra directory scrivibile dall'utente con priorità superiore a /usr/bin , quindi potrei semplicemente collegare simbolicamente ./sl a /bin/bash .
Ha importanza che tipo di binario/ELF è il file SUID radice?
Sì, perché il bit SetUID viene ignorato negli script di shell. Deve essere un eseguibile nativo.