Il permesso di esecuzione di Unix può essere facilmente aggirato. È superfluo, o qual è l'intenzione dietro di esso?

58

L'autorizzazione di lettura di unix è in realtà la stessa del permesso di esecuzione, quindi se ad es. un processo ha accesso in scrittura è anche in grado di eseguire lo stesso file.

Questo può essere fatto abbastanza facilmente: prima questo processo deve caricare il contenuto del file, che deve essere eseguito, in un buffer. Successivamente chiama una funzione da una libreria condivisa che analizza l'ELF nel buffer e la carica negli indirizzi giusti (probabilmente sovrascrivendo il vecchio processo come al solito, quando chiama execvp). Il codice salta al punto di ingresso del nuovo programma e viene eseguito.

Sono abbastanza sicuro che Dennis Ritchie e Ken Thompson fossero a conoscenza di questo problema. Quindi, perché hanno persino inventato questa autorizzazione, qual è l'intenzione dietro di essa e qual è il senso di essa, se non può impedire l'esecuzione di qualsiasi processo di qualsiasi utente che abbia accesso in lettura? C'è anche un tale senso o è superfluo?

Potrebbe anche essere un serio problema di sicurezza, ci sono dei sistemi, che si basano sulla forza delle autorizzazioni rw- o r--?

    
posta Martin Erhardt 02.09.2014 - 01:28
fonte

6 risposte

80

Esiste un modo ancora più semplice per ignorare il permesso di "esecuzione": copia il programma in una directory di tua proprietà e imposta il bit "esegui".

L'autorizzazione "esegui" non è una misura di sicurezza. La sicurezza viene fornita ad un livello inferiore, con il sistema operativo che limita le azioni specifiche. Ciò avviene perché, in molti sistemi simili a Unix (specialmente nei giorni di Ritchie e Thompson), si presume che l'utente sia in grado di creare i propri programmi. In una situazione del genere, l'utilizzo dell'autorizzazione "esegui" come misura di sicurezza è inutile, poiché l'utente può semplicemente creare la propria copia di un programma sensibile.

Come esempio concreto, eseguendo fdisk come utente non privilegiato per provare a codificare la tabella delle partizioni del disco rigido:

$ /sbin/fdisk /dev/sda 

Welcome to fdisk (util-linux 2.24.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

...

Changed type of partition 'Linux' to 'Hidden NTFS WinRE'.

Command (m for help): w
fdisk: failed to write disklabel: Bad file descriptor

L'ultima riga è fdisk che tenta di ottenere un descrittore di file "write" per il disco rigido e in mancanza, perché l'utente che sto eseguendo non ha il permesso di farlo.

Lo scopo del permesso "esegui" è duplice: 1) dire al sistema operativo quali file sono programmi e 2) per dire all'utente quali programmi possono essere eseguiti. Entrambi sono consigli piuttosto che obbligatori: puoi creare un sistema operativo perfettamente funzionante senza il permesso, ma migliora l'esperienza dell'utente.

Come indica R .., c'è un caso particolare in cui il permesso "esegui" è usato per sicurezza: quando un programma ha anche il bit "setuid" impostato. In questo caso, l'autorizzazione "esegui" può essere utilizzata per limitare chi è autorizzato a eseguire il programma. Qualsiasi metodo per bypassare l'autorizzazione "Esegui" eliminerà anche lo stato "setuid", quindi non c'è alcun rischio per la sicurezza qui.

    
risposta data 02.09.2014 - 03:40
fonte
26

È possibile impostare il bit di esecuzione, ma non il bit di lettura, su un file eseguibile. In questo modo, nessuno sarà in grado di copiare il file, ma le persone possono eseguirlo comunque.

Questo è abbastanza inutile oggi, perché a) funziona solo con programmi compilati, non con script (sulla maggior parte dei sistemi); b) in questi giorni, con il 90% di tutti gli unix che sono linux, le persone possono copiare gli eseguibili da qualsiasi luogo e c) lo spazio su disco utilizzato da un eseguibile copiato non ha molta importanza.

Tuttavia, ci sono stati usi per questo nei vecchi tempi.

The Unix system i used at school, 30 years ago, was very limited in RAM and Disk space. Especially, the /usr/tmp file system was very small, which led to problems when someone tried to compile a large program. Of course, students weren't supposed to write "large programs" anyway; large programs were typically source codes copied from "somewhere". Many of us copied /usr/bin/cc to /home/<myname>/cc, and used dd to patch the binary to use /tmp instead of /usr/tmp, which was bigger. Of course, this just made the problem worse - the disk space occupied by these copies did matter those days, and now /tmp filled up regularily, preventing other users from even editing their files. After they found out what happened, the sysadmins did a chmod go-r /bin/* /usr/bin/* which "fixed" the problem, and deleted all our copies of the C compiler.

Un altro uso è dire alla shell quali file sono destinati ad essere eseguiti e quali no. Non vuoi un file di testo casuale eseguito perché hai digitato il suo nome; il bit x fornisce un modo per impedirlo. (In questi giorni, la shell poteva solo guardare l'inizio del file, e solo eseguirlo se inizia con #! , ma questo è stato introdotto molto più tardi). Anche la funzione di completamento di bash suggerisce i file con bit eseguibili solo quando stai digitando un comando.

    
risposta data 02.09.2014 - 10:07
fonte
7

Esiste un modo readymade per eseguire un file arbitrario: passalo come argomento al linker dinamico (che è l'interprete appropriato per un eseguibile caricato dinamicamente). Per esempio. sotto Linux,

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/ld-linux.so.2 /tmp/ls

Tuttavia, questo include la stessa restrizione della lettura del file e il passaggio al codice: i bit setuid non vengono valutati.

In passato disponevamo spesso di binari come /bin/su :

-rwsr-xr-- root wheel  ...  /bin/su

Solo i membri del gruppo wheel , che gli amministratori di sistema mantenevano tagliati alle persone che conoscevano la password root sarebbero anche in grado di eseguire il comando su , quindi anche se un overflow del buffer esisteva in quel binario, consentendo ai chiamanti per bypassare la sicurezza, l'exploit sarebbe utilizzabile solo da persone che conoscono comunque la password.

    
risposta data 02.09.2014 - 17:46
fonte
5

Sono sorpreso che nessun altro abbia fatto riferimento a un altro uso di + x bit: le directory. Forse sei dopo l'esecuzione di (esempio) qualcosa in / bin (script di shell o altro), ma c'è più di eseguire bit che file (ovviamente, una directory è un file ma è un diverso tipo di file).

Se hai + x accesso su una directory ma -r sulla stessa directory, avrai le seguenti funzionalità:

  • Se conosci il nome di un file (o directory) in quella directory, puoi elencarlo (ad esempio, ls su di esso). Devi comunque conoscere il nome.
  • Non puoi cambiarlo (tramite comando cd o chdir system call).

Se tuttavia hai -x e + r, puoi fare quanto segue:

  • Non puoi modificare la directory (come sopra)
  • Puoi elencare i file. Ma dal momento che non hai + x l'accesso alla directory, non puoi accedere ai file stessi.
  • Questo significa anche che non puoi aggiornare (solo timestamp o altro) e non puoi nemmeno aprirli in un editor di testo (o cat, o ...).

Se hai + rx allora puoi fare tutto questo (eccetto che hai bisogno di + w per scrivere nella directory stessa, cioè creare nuovi file, la modifica dei file funziona, la rimozione no, la creazione no)

E sì, questo significa che alcune persone possono vedere o modificare i file ma solo se conoscono il percorso esatto (purché abbiano i diritti di modificare, comunque). E sì: ls è una lista e serve per cercare le directory. Quindi, in sintesi: l'esecuzione di una directory si sta modificando (per qualsiasi motivo). Ovviamente i bit sono tutti insieme ciò che conta davvero.

    
risposta data 03.09.2014 - 20:42
fonte
4

Se per qualche ragione vuoi mantenere segreto il codice binario, puoi rendere il programma eseguibile senza essere leggibile. Questo non è utile se gli utenti hanno accesso fisico alla macchina. Inoltre, non è utile se il codice sorgente o binario è ampiamente disponibile. Quindi questo è un caso d'uso abbastanza limitato.

Se il programma ha un bit setuid o setgid, l'accesso in esecuzione fa qualcosa in più rispetto a ciò che può essere ottenuto leggendo il file binario. Un approccio è quello di creare un eseguibile setuid che è eseguibile solo per un gruppo specifico. Se era leggibile in tutto il mondo, le persone esterne a quel gruppo non potevano ancora copiarlo e utilizzare il bit setgid nell'eseguibile originale. (Anche se nella maggior parte dei casi preferisco usare setgid che setuid, e poi usare il gruppo sulla directory per controllare chi può accedere all'eseguibile.)

Solitamente il bit eseguibile viene semplicemente usato per indicare quali file sono programmi in primo luogo. In questo modo il completamento può funzionare meglio e non si eseguono accidentalmente eseguibili indesiderati.

Se vuoi impedire agli utenti di copiare un eseguibile ed eseguirlo, puoi montare le home directory con noexec . Affinché ciò abbia senso, devi utilizzare noexec per ogni file system, in cui l'utente può scrivere qualsiasi cosa.

    
risposta data 02.09.2014 - 14:40
fonte
2

L'autorizzazione bit di esecuzione viene verificata dal kernel all'esecuzione della chiamata di sistema exec (2) (e cugini). Ne avrai bisogno solo per eseguire programmi a livello di kernel.

Solo i programmi con quel bit attivato (a seconda di quali siano i risultati che ti riguardano come proprietario, gruppo o altro è quello che viene controllato) possono essere exec () ed dal kernel.

Un'altra cosa diversa è ciò che fa la shell quando interpreta uno script di shell o perl, o qualunque interprete tu possa avere. Sugli script, il kernel controlla il #!... all'inizio del file come un numero magico, e lancia la shell indicata lì (sarà necessario anche il permesso di esecuzione per la shell), e tu hai bisogno di legge i permessi su quello script, dato che la shell deve aprirlo e leggerlo per essere interpretato. Per gli script di shell è necessario avere il permesso di lettura e l'autorizzazione all'esecuzione. Ma per gli script di shell è necessario il permesso di lettura solo , poiché è sempre possibile eseguire uno script di shell eseguendo la shell e passando lo script della shell come parametro (o file di input) )

Ovviamente, come è stato indicato, il bit di esecuzione può essere aggirato copiando il programma e rendendolo eseguibile, ma non potrai copiarlo se non hai i permessi di lettura per fare quella copia (continui a essere in grado di eseguirlo).

Prova a modificare (come root ovviamente) le autorizzazioni per ls (1) e renderlo 0111 ( ---x--x--x ) e provare a fare una copia eseguibile di esso e vedere come impossibile ottenere la tua copia eseguibile, anche quando continui ad essere in grado di eseguirla.

Sulle directory, eseguire bit significa una cosa diversa. Il kernel usa il permesso ' x ' durante l'iterazione attraverso il percorso (nella funzione kernel namei () ) quindi se non si dispone di autorizzazioni di esecuzione su una directory, non è possibile né utilizzarlo, né i file accessibili attraverso di esso. Anche tu puoi leggere un contenuto di directory con permessi di lettura, ma non puoi accedere ai file in esso contenuti. Oppure, al contrario, puoi avere permessi di esecuzione su una directory ma non avere accesso in lettura, e sarai in grado di utilizzare i file all'interno, ma non sarai in grado di vedere il contenuto della directory.

    
risposta data 04.09.2014 - 14:07
fonte

Leggi altre domande sui tag