|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
chroot
per un progetto universitario (lo stesso percui qualche giorno fa chiedevo delle inotify) dovrei realizzare un server che periodicamente notifichi i suoi clients delle modifiche effettuate al filesystem, solo a partire da una certa cartella; ovvero i clients devono poter richiedere il controllo e la ricezione di notifiche solo relativamente a cartelle radicate in una certa cartella specificata dall'amministratore all'avvio del server. inoltre il programma deve essere realizzato sia per Windows che per Linux. è logico che per Linux mi è saltato immediatamente in testa il concetto di chroot :P
in teoria potrei impedire ai clients il controllo di cartelle al di sopra della root semplicemente facendo un parsing del path richiesto e controllando che: 1) sia valido senza dover uscire dalla root 2) non contenga riferimenti alla cartella .. , cosa che un utente malizioso potrebbe sfruttare per risalire pur immettendo un path valido nella root. però piuttosto che fare parsing per cercare di dedurre dove esattamente punta il path, preferirei una soluzione più robusta ed elegante basata su chroot su Linux e restricted tokens su Windows. coi restricted tokens me la vedo io ![]() come potrei architettare il tutto? dovrei richiedere all'amministratore che il server venga avviato come root per poter fare chroot, e una volta fatto dovrei forkare creando il processo server figlio non come root ma come un altro utente impossibilitato a chroot-are? il fatto che il server sia impossibilitato a chroot-are è una cosa che mi piacerebbe fare a scanso di exploit, ma al limite se è troppo complicata posso anche lasciar perdere perché il server (sperando di non averci lasciato dei bug) non prevede in nessun caso l'esecuzione nel suo processo di codice o comandi untrusted. semplicemente accetta dei path e si mette a controllarli in attesa di modifiche. grazie |
|
|
|
|
|
#2 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
up
non pretendo che qualcuno dia retta alle mie nerdate nel uichend, ma uppo giusto per non farlo andare nei meandri del forum ilsensine, dove sei?? i tuoi aiuti sono sempre preziosi
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
E' un metodo sicuro ed elegante, ma sì, devi lanciare il server da root (per ovvi motivi di sicurezza: immagina un programma con suid bit attivo, tipo 'passwd', che accede ad una chroot jail formata ad hoc (ad esempio con un falso /etc/passwd)...)
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 12-05-2007 alle 16:59. |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
non ho capito una mazza di quello che devi fare
per quanto riguarda l'esplorazione delle directory mi è subito saltata in mente os.walk di python. Per quanto riguarda il tuo problema... quale sarebbe? che devi verificare che l'utente abbia i diritti per accedere in lettura alla cartella? ![]() P.S. si nota che non ho la minima idea di quello ke fa chroot? P.P.S ora ho letto il link che sull'LCD non l'avevo nemmeno notato
__________________
Ultima modifica di ^TiGeRShArK^ : 12-05-2007 alle 16:52. |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
Per un server di rete, questo è molto sicuro, perchè anche in presenza di un bug, il client remoto può solo fare danni all'iterno di quella directory, e non può invece andare altrove (visto che il processo server vede quella directory come la radice del FS...). Come controindicazione, un programma che fa chroot via codice DEVE avere tutte le risorse e le librerie caricate dinamicamente DENTRO la directory in cui fa chroot (altrimenti non potrebbe caricarle perchè non le troverebbe), oppure precaricare tutto e poi fare chroot. Ovviamente, se il processo che fa chroot non cede i privilegi di root subito dopo, il tutto diventa inutile.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
ok .. ora mi è chiaro cosa faccia chroot.. ma mi sfugge perchè fare tutto ciò.. non sarebbe meglio usare sempre path relativi e nel caso ci sia un path assoluto impedire l'esecuzione? con i path relativi si può risalire solo alle cartelle sotto quella corrente, quindi basterebbe controllare che il path non contenga ".." e/o "/" all'inizio della stringa... o no?
__________________
|
|
|
|
|
|
|
#7 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
dunque dunque... innanzitutto grazie fidel, utillima (
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
dir_in_server/../../../../etc/ cosa succede? Il parsing è pericoloso, deve essere davvero robusto.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson |
|
|
|
|
|
|
#9 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
|
|
|
|
|
|
|
#10 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
|
|
|
|
|
|
|
#11 | |||
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
Quote:
Quote:
Con setsid puoi anche disassociarti dal terminale di controllo per rendere il server immune a certi segnali (insomma lo puoi rendere un "demone" (o meglio daemon)).
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 12-05-2007 alle 18:43. |
|||
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson |
|
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
__________________
|
|
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
__________________
|
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
cmq tornando IT..
direi che ad occhio in mezzo a tutte le properties ke è possibile specificare nel SecurityManager di Java qualcuna che faccia al caso tuo si trova per forza
__________________
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
Vabbé, fai conto che su linux puoi anche chiamare un file "/../" ad esempio Per avere massima flessibilità bisognerebbe appunto implementare il path parser già implmentato nel SO, meglio non reinventare la ruota (tra l'altro ben fatta e collaudata in tanti anni
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson |
|
|
|
|
|
|
#17 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson |
|
|
|
|
|
|
#18 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
fidel, mi sono guardato il man delle varie syscall che hai detto e ho scoperto l'esistenza di effective uid, real uid, e saved uid. da quello che ho capito il real uid è l'user id sotto il quale gira il processo, l'effective è quello effettivo (cioè quello che realmente determina se il processo può o non può accedere a questa o quella risorsa), e il saved è un uid salvato che serve a riottenere permessi elevati quando vi si rinuncia. è più che altro un'idea che mi sono fatto leggendo le syscall, ma non ho trovato una definizione precisa di questi tre uid, quindi correggimi se ho sbagliato. io nel mio caso quale dei tre dovrei settare? nel man leggo a proposito di setuid (che setta quello effettivo, a proposito: che differenza c'è tra setuid e seteuid?) che se l'uid effettivo corrente è il super-user allora tutti e tre gli uid vengono settati al nuovo uid, di conseguenza un processo che usa questa syscall per rinunciare ai privilegi di root non può ridiventare root. ciò basta ai miei scopi? è sufficiente che io richieda all'amministratore l'avvio da root, poi chiami chroot ed infine setuid? e l'uid_t che serve a me da dove lo piglio?
|
|
|
|
|
|
#19 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
Un utente sul sistema ha un unico UID (user ID) che specifica le risorse al quale l'utente può accedere. Stessa cosa per il group ID (GID). Un processo sul sistema, invece, ha 3 UID: 1) UID reale: specifica il proprietario del processo 2) UID effettivo (EUID): usato nella decisione di quali risorse il processo può usare 3) UID salvato: per un ripristino futuro dell'UID in caso di cambio UID. Stessa cosa per il GID (3 GID). Un processo (creato o forkato), ha inizialmente come EUID l'UID reale (quindi quello del proprietario del processo). Visto che solo l'utente root può modificare l'UID reale del processo, cosa accade quando un utente non privilegiato chiama setuid()? Questo era lasciato all'implementazione di setuid(), diversa di solito tra i vari sistemi *nix, visto che lo standard POSIX 1 prevede solo la syscall setuid(). Quindi è stata introdotta la syscall seteuid(), per cambiare l'UID effettivo da parte di utenti non privilegiati (ovviamente non puoi mai avere privilegi superiori a quelli dati dall'UID reale Perchè tutto questo? Per avere flessibilità: se io utente non privilegiato potessi cambiare l'UID reale, ad esempio rilasando i permessi, non potrei più tornare all'UID precedente, con privilegi più elevati. Con seteuid invece, un processo non privilegiato (UID reale non privilegiato) può tranquillamente cambiare/rialssare i permessi con seteuid (visto che è con l'EUID che il kernel decide l'accesso alle risorse) per poi poter riprendere i privilegi dell'uid reale. Come puoi immaginare, a te tutto questo non interessa per niente, visto che lancerai il server come root. Quindi, userai solo setuid() e setgid(). E' anche molto più sicuro, visto che, cambiando l'UID ed il GID reali, NON potrai più, in un secondo momento, riprendere i permessi (anche in presenza di un bug), perche l'EUID non può scavalcare l'uid, ed il processo NON PUO' PIU' cambiare l'uid reale (perchè è diventato non privilegiato) ma solo quello effettivo. I permessi di un processo privilegiato vanno rilassati cambiando quindi l'UID e il GID reali, che sono il "tetto" dell'EUID. Quindi farai: 1) setuid() ad un user non privilegiato 2) setgid() ad un gruppo non privilegiato. Ovviamente potresti anche usare una execve: in modo figo, fai un programmino "wrapper" che crea una chroot jail, abbassa i privilegi e lancia il tuo server (che sarà un eseguibile esterno): in questo modo il server sarà multipiattaforma (con linux lo lanci con il wrapper, su altri sistemi lo lanci direttamente) ed il wrapper sarà "universale" (applicabile a tutti i programmi che vuoi). Giusto per completezza La domanda adesso sorge spontanea: come scelgo il nuovo UID e GID, da dove li prendo?. Partendo dal presupposto che UID e GID possono assumere i valori di uno tra gli UID e GID presenti sul sistema ospite del processo, dobbiami scegliere l'utente ed il gruppo appropriato, che deve esistere sul sistema. Normalmente, i programmi chrooted, come ad esempio Apache o Postfix, creano in fase di installazione un utente/gruppo ad hoc (Apache ad esempio crea l'utente 'wwwrun', Postifix crea l'utente 'postfix'), che hanno i giusti privilegi solo nelle loro cartelle, e sul resto del sistema sono sempre visti come "other" (quindi al massimo hano privilegi di lettura). Quindi potresti creare un utente ad hoc, ottenere via codice uid e gid associati e settare quelli. Hai però un'altra soluzione, se, come penso, non vuoi mettere mani al sistema, ma semplicemente lanciare il tuo server chrooted in modo sicuro su qualiasi sistema *nix, senza intervenire sul sistema stesso. Bene, quello che può al caso tuo è l'utente 'nobody', che ha UID=65534 e GID=65533. 'nobody' qualche privilegio ce l'ha (di solito sul database di "locate" ad esempio) ma mi sembra un buon utente per una chroot (visto che non puoi agire al di fuori della chroot dopo averla creata, e un utente non privilegiato non puo "scappare dalla prigione"). In codiice, quindi, puoi fare: Codice:
...
/* apro le risorse esterne alla chroot */
...
if (chroot(path))
{
/* gestione errore */
exit(1);
}
if (setgid(65533))
{
/* gestione errore */
exit(1);
}
if (setuid(65534))
{
/* gestione errore */
exit(1);
}
Un'ultima nota: se non vuoi problemi con il caricamento di librerie condivise dopo aver fatto chroot, puoi tranquillamente linkare staticamente quando compili il server. EDIT: dimenticavo, per completessa: Il kernel GNU/Linux prevede anche un quarto uid/gid: è il Filesystem UID (FSUID) che regola i permessi di accesso al filesystem. Ovviamente, in caso di chiamata a setuid(), FSUID prende il valore di UID. EDIT 2: Ah, se non puoi avere la certezza che all'utente nobody (come a qualunque altro utente) sia associato proprio quell'UID/GID, per conoscerli a partire da un username puoi usare la funzione getpwuid(uid_t uid) presente in "pwd.h". Fai "man getpwuid()" per saperne di più - anche per gli headers da includere - oppure, in modo più bello, apri Konqueror e digita come indirizzo "man:/getpwuid" EDIT 3: eliminata la fork(), inutile.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 15-05-2007 alle 09:41. |
|
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
![]() che casino ![]() con java in teoria basterebbe far partire il server specificando un securityManager che abbia questo permesso: java.io.FilePermission "./*", "read" in questo modo dovresti avere accesso in lettura a tutti i file al di sopra della dir corrente (o eventualmente puoi specificare un'altra dir). Per quanto riguarda la portabilità.. bhè.. immagino che sia garantita quantomeno tra windows e linux
__________________
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 11:46.























