sabato 30 giugno 2012

È permesso ?

Uno degli aspetti più interessanti dei sistemi operativi Posix è sicuramente la semplicità dei concetti su cui si basano, tanto che chiunque abbia tentato di stravolgere questi concetti inventandosi nuove strategie, ha finito per complicare enormemente le cose e conseguentemente ha dovuto correre ai ripari.

Pensiamo per esempio ai permessi. Per capire i permessi di Unix anni fa, mi è bastato leggere un paio di pagine di un libro e fare due prove su un HP-UX , ma le potenzialità di una simile gestione, dei livelli di accessi degli utenti, dei gruppi e di root, è passata con nonchalance dai mainframes ai telefoni Android.

Suid e Guid

Il sistema dei permessi di Linux come delle altre macchine Posix è piuttosto rigoroso.

Sappiamo che il kernel, dopo avere predisposto le varie funzionalità lancia un programma e lo fa con delle righe di codice sorgente, sublimi nella loro semplicità :

Estratto di init/main.c 



 ...

 /*
  * We try each of these until one succeeds.
  *
  * The Bourne shell can be used instead of init if we are
  * trying to recover a really broken machine.
  */
  if (execute_command) {
      run_init_process(execute_command);
      printk(KERN_WARNING "Failed to execute %s.  Attempting "
                  "defaults...\n", execute_command);
  }
  run_init_process("/sbin/init");
  run_init_process("/etc/init");
  run_init_process("/bin/init");
  run_init_process("/bin/sh");

  panic("No init found.  Try passing init= option to kernel. "
        "See Linux Documentation/init.txt for guidance.");

...

 


Belle vero ?

Comunque, che abbiate apprezzato o meno, sappiate che al processo init è assegnato un PID 1 e un UID di processo uguale a 0, quindi dall'alto della sua posizione di root, init lancia tutta una serie di processi aggiuntivi, come i servizi e i login.

Sono proprio i login che vanno a curiosare nel file passwd, per cercare l'utente che vuole loggarsi e poi, dopo avere verificato i suoi diritti col vecchio sistema del confronto hash o col moderno sistema delle pam, cambia l'UID con quello dell'utente loggato, il quale non essendo presumibilmente root non potrà più cambiarlo, convalidando così tutto il sistema dei permessi.

In questo modo all'utente non sarebbe mai concesso di diventare root senza eseguire una login come tale o senza valide scappatoie, tipo agire attraverso un servizio, come quelli che mettono a disposizion gdm e kdm quando un utente chiede per esempio lo shutdown.

Esiste però un altro modo, si chiama bit di suid, il quale apre tutta una serie di possibilità e di vulnerabilità che spesso i sistemisti amano rimuovere con l'apposita opzione di mount "nosuid" sui volumi bollenti.

Se infatti è impostato il bit 11, cioè il famoso bit di "set uid", su un file eseguibile, quando il nostro valoroso processo, tenterà di "eseguire", il file cambierà assumendo automaticamente l'UID dell'utente proprietario che di solito è root, che è comunque l'unico utente in grado di impostare questo bit su un file.

Per completezza diremo che esiste anche il bit 10  "set gid", che invece cambia il solo gruppo dell'utente ma è poco usato.
 
Se andiamo a vedere per esempio il programma sudo che permette di eseguire altri programmi come super user,  scopriamo che i suoi permessi sono :


ls -l /usr/bin/sudo
-rw
sr-xr-x 2 root root 75456 May 24 19:36 /usr/bin/sudo

e con somma sorpresa scopriamo che usa il suid bit che gli permette di diventare tranquillamente root.

Sarebbe bello poterlo fare con uno script, ma il sistema non funziona in generale con gli interpreti ma solo coi files direttamente eseguibili e questo ci fa capire qual'è il modo migliore per bypassare i controlli.

Grimaldello

Per capire bene come funziona e con quali limitazioni il suid,  scriviamo un piccolo grimaldello.


/* Grimaldello */

#include <stdio.h>
#include <unistd.h>


int main(int ac,char **av)
{
  if (ac<2) return 1;
  system(av[1]);
  return 0;
}


 

Quindi compiliamolo e mettiamo a posto i permessi da root :

gcc grimaldello.c -o grimaldello
sudo chown root:root grimaldello
sudo chmod 4755 grimaldello


Ora proviamo da dare :



./grimaldello whoami
root

Il fatto che il nostro grimaldello ci abbia risposto root, ci fa intuire la mostruosità che abbiamo appena creato, una vulnerabilità di altissimo livello, concedendo a chiunque di eseguire programmi come root, infatti con :



./grimaldello sh
#



otteniamo una stupenda Shell suidata.

Mentre con :


./grimaldello bash
bash-4.2$


Non otteniamo nulla ! Perché la bash come i programmi scritti con le GTK e molti altri, rifiuta questo meccanismo.

Se però inseriamo una semplice riga al nostro programma :



/* Grimaldello */

#include <stdio.h>
#include <unistd.h>


int main(int ac,char **av)
{
  if (ac<2) return 1;
  setuid(0);
  system(av[1]);
  return 0;
}


 
ecco che il grimaldello diventa più aggressivo.


/grimaldello bash
#


e lascio a voi il cercare di capire perché.

Bene, ora che avete capito come funziona grimaldello, cancellatelo.


Pumpkin

Con la stessa logica di grimaldello, possiamo creare un programma che invece potrebbe essere utile, a scopo didattico e non.

Spesso chi è abituato alla gestione della rete e delle cartelle condivise, tende a confondere il concetto di "gruppo di lavoro" inteso come gruppo di persone con il permesso condividere una certa cartella e il gruppo di lavoro dei permessi Posix.

Ciò non è linea di massima un errore ma un'enorme limitazione.

Infatti mentre nel primo caso si tratta di permesso di accesso ai dati, nel secondo si parla di permesso di accesso anche all'hardware della macchina e ai suoi canali di comunicazione, perché nel file system ci sono anche i devices e i files speciali che controllano tutto (tranne le socket e la gestione della rete) e si può proibire l'accesso a intere categorie di utenti e permettere ad altri di fare cose che altrimenti potrebbe fare solo root.

Per esempio sulla maggior parte dei sistemi se un utente limitato non appartiene al gruppo "video" non ha accesso alla telecamera e questo può essere interessante per limitare le funzionalità "invasive" di certi programmi di chat.

Pensate a programmi  closed source, programmi di file sharing che spesso girano per giorni indisturbati sulla macchine o programmi che se ne stanno in background, potrebbero presentare vulnerabilità più o meno volute, e accedere alle risorse della macchina indisturbati.

Anche senza voler essere paranoici, l'errore o l'idiozia la si trova ovunque e capita spesso di vedere sulle reti di condivisione, interi dischi condivisi, compresi documenti, foto, numeri di telefono password e mail.

Comunque, mediante questo sistema è possibile creare un utente che sulla mia macchina ho chiamato pumpkin (invece di sandbox), con permessi molto limitati.

Poi si può poi proteggere la propria home con chmod 750, precludendo l'accesso a tutti coloro che non sono nel vostro gruppo di lavoro (compreso pumpkin).

Diamo per scontato che è possibile con alcune interfacce grafiche, avviare un programma a nome di un altro utente, in questo caso è richiesta la password.

Per evitare la password si può modificare il file di configurazione di sudo , che è piuttosto complesso, perché di solito bisogna calibrare il comportamento su ogni programma o concedere l'accesso comune senza password.

Per testare i vari programmi o per lanciare programmi in background, si può usare un programma simile a grimaldello che ho chiamato pumpkin :


/* Pumpkin */

#include <stdio.h>
#include <unistd.h>


int main(int ac,char **av)
{
  if (ac<2) return 1;
  setuid(5000);
  setenv("USER","pumpkin");
  setenv("HOME","/home/pumpkin");
  execv(av[1],av+1);
  return 0;
}
 

Come vedete ho messo in hard coding sia lo user-id che ho fissato a 5000 che la HOME che la USER, così evito che vi possano essere problemi.

Il programma ha i seguenti permessi :


-rwsr-x---   1 root  user 7114 Jun 30 16:28 pumpkin

Quindi vediamo che è solo leggibile e eseguibile da user che sono io o siete voi ed è modificabile solo da root, che è il proprietario e ha il bit di suid.

Il programma è stato messo in /local/bin.

Con il comando :

pumpkin /usr/bin/<il programma di file sharing>


anche senza sudo, il programma di file sharing, partirà localmente ma come utente pumpkin, che lavora nella sua cartella riservata e con pochissimo accesso al disco, senza possibilità di fare danni, accedere al video eccetera.

E la grafica ?

Ovviamente se avete aperta una sessione X dal vostro utente user, è improbabile che il programma grafico,visualizzi qualcosa, per motivi di sicurezza.

Occorre lanciare un comando di apertura di X server, quello che dà permesso a tutti da chiunque è :

xhost +

fino a qualche anno fa scrivere questo comando era una oscenità ma oggi sulla maggior parte degli Xserver, l'accesso fuori da localhost non è ammesso se non su esplicita richiesta, se volete essere più restrittivi ci dovete lavorare un po`.

Quando va lanciato ?

Ma naturalmente dopo avere avviato l'XServer dalla vostra sessione grafica, io per esempio ho fatto uno script :


#!/bin/bash
/usr/bin/xhost +

e l'ho messo in un file :

~/.kde/Autostart/xhostplus
ovviamente eseguibile ;).

Nessun commento:

Posta un commento