Gestione della sicurezza nel sistema Android

Transcript

Gestione della sicurezza nel sistema Android
Scuola Politecnica e delle Scienze di Base
Corso di Laurea in Ingegneria Informatica
Elaborato finale in Sistemi Operativi
Gestione della sicurezza nel sistema
Android
Anno Accademico 2014/2015
Candidato:
Giuseppe Guida
matr. N46000585
A mio padre.
Indice
Indice .................................................................................................................................................. III
Capitolo 1: Introduzione al progetto Android ...................................................................................... 4
Capitolo 2: Android Security Framework ............................................................................................ 8
2.1 Sandboxing............................................................................................................................... 10
2.2 Permessi Linux e Capabilities .................................................................................................. 11
2.3 Permessi Android ..................................................................................................................... 13
2.4 SELinux e SEAndroid .............................................................................................................. 17
2.5 Firma dei package .................................................................................................................... 20
Capitolo 3: Sicurezza del dispositivo fisico ....................................................................................... 23
3.1 Boot .......................................................................................................................................... 23
3.2 Crittografia ............................................................................................................................... 25
3.3 Screen Lock.............................................................................................................................. 26
3.3 Sicurezza del Radio Interface Layer ........................................................................................ 27
Conclusioni ........................................................................................................................................ 30
Bibliografia ........................................................................................................................................ 31
Lista delle Figure ............................................................................................................................... 32
Capitolo 1: Introduzione al progetto Android
Nel 2005 la Google Inc. rilevò dal mercato la Android Inc., azienda specializzata nello
sviluppo di sistemi embedded basati sul kernel di Linux, per poter dar vita ad un proprio
progetto di sistema operativo mobile. La prima versione di Android fu terminata nel
Novembre del 2007 e messa in commercio a partire da Settembre 2008, da allora si sono
succedute molte versioni del sistema operativo ed ognuna di esse ha introdotto novità e
raffinamenti rispetto ai modelli precedenti.
Tuttavia la filosofia che sta dietro allo sviluppo del sistema operativo mobile non è mai
cambiata, essa rispecchia fedelmente la filosofia alla base di Linux, Android infatti è un
progetto open source noto come AOSP (Android Open Source Project) quindi il suo
codice può essere usato, distribuito e modificato liberamente da chiunque. Il primo
riverbero della filosofia dell’Android Open Source Project si è avuto con la sigla
4
dell’accordo noto come Open Handset Alliance (OHA) il quale prevede che tutte le
aziende stipulanti, guidate da Google, impieghino risorse per sviluppare standard open
source per i dispositivi mobili.
Come per la filosofia così per gli obiettivi principali di Android tutto è rimasto immutato
dalle prime versioni, essi possono essere sintetizzati nei seguenti punti:
1. Provvedere ad un sistema di Application Programming Interface (API) capace di
gestire il maggior numero possibile di applicazioni sviluppate da terze parti, quindi
anche con codice proprietario.
2. Permettere a tutte le applicazioni sviluppate da terze parti di competere fra loro
lealmente, cercando di fornire servizi eguali a ciascuna di esse, come la
sincronizzazione dei dati o lo scambio dei messaggi tra cloud e dispositivo.
3. Semplificare la vita all'utente facendo sì che esso debba spendere il minor tempo
possibile ad occuparsi di questioni inerenti alla gestione dei processi applicativi.
4. Avvicinarsi sempre più ad un sistema operativo mobile full general-purpose come i
sistemi operativi dei computer desktop.
5. Fornire un modello di sicurezza che protegga non solo il sistema operativo, ma
anche le applicazioni di terze parti e la privacy dell'utente.
Cenni sull’architettura
L’architettura di Android può essere rappresentata come uno stack composto da quattro
strati fondamentali, analizzandola in prospettiva bottom-up abbiamo: lo strato del kernel
Linux, lo strato Native Userspace, lo strato Application Framework ed infine lo strato
Applicazioni. Spesso ci si riferisce ai due strati centrali come Android Middleware.
5
I
l
Il kernel Linux presente in Android fornisce tutte le funzionalità tipiche di un sistema
operativo Unix: i driver per comunicare con l’hardware, funzionalità di rete, accesso al file
system e gestione dei processi. Tuttavia il kernel di Android introduce delle aggiunte
rispetto al normale kernel di Linux, queste aggiunte sono chiamate Androidismi e servono
a rendere il sistema operativo più adatto a dispositivi mobili. Gli Androidismi sono:
il Binder, il Paranoid Networking, i wakelocks, la ashmem (anonymous shared memory),
gli alarms ed il low memory killer; dal punto di vista della sicurezza i primi due rivestono
una grande importanza in quanto il binder implementa il meccanismo di IPC e il paranoid
networking gestisce l’accesso alla rete.
Il Native Userspace è formato da quattro componenti fondamentali: l’Init, i daemons
nativi, le librerie native e l’Hardware Abstraction Layer (HAL). L’Init è il primo processo
ad essere eseguito dopo la fase di booting, esso dà inizio a tutti gli altri. I daemons nativi
sono dei processi propri del sistema operativo che forniscono funzionalità essenziali al
dispositivo, ad esempio il rild (radio interface level daemon) si occupa della
comunicazione tra il processore in banda base e gli altri componenti. Le librerie native
sono librerie caricate dinamicamente e servono i processi nelle più disparate modalità.
L’Hardware Abstraction Layer è un’interfaccia che gestisce i moduli driver e le relative
6
API forniti dai costruttori di hardware senza conoscerne i relativi dettagli implementativi.
L’Application Framework è composta dalla Dalvik virtual machine, dalle Java Runtime
Libraries, dai System Services e dalle Android Framework Libraries. La Dalvik Virtual
Machine è una Java Virtual Machine costruita su misura per Android, essa non è in grado
di leggere i file .class del linguaggio Java in quanto è stata progettata per leggere i file
DEX (Dalvik EXecutable) i quali sono raggruppati in file con estensione .dex, questi
ultimi a loro volta sono raccolti in un file APK (Android Application) o JAR (Java
libraries). Le Java Runtime Libraries supportano il codice scritto in linguaggio Java,
poiché la gran parte di Android è scritta proprio in questo linguaggio, la presenza di queste
librerie è fondamentale. Tutte le funzionalità che il sistema operativo ha da offrire sono
racchiuse nelle System Services, esse comprendono ad esempio: la connettività di rete, il
supporto del display touch screen e la telefonia. Il linguaggio dominante per
l’implementazione delle System Services è il Java, ma possono essere anche scritte in
codice nativo. Quasi tutte le funzionalità forniscono un’interfaccia utilizzata dalle altre
funzionalità o dal livello superiore per comunicare o chiedere servizi. Infine le Android
Framework Libraries raccolgono tutte le librerie Java che non sono incluse nelle Java
Runtime Libraries.
Lo strato Applications è destinato a contenere le app che compongono Android, le app si
dividono in built-in apps ed user apps. Le prime sono incluse nel sistema operativo mentre
le seconde sono scaricate manualmente dell’utente da uno dei numerosi app market.
Android è ad oggi il sistema operativo mobile più diffuso al mondo. Il numero totale di
dispositivi che lo utilizzano è stimato per oltre un miliardo di unità, inoltre gli analisti
prevedono che una crescita continua per tutto il prossimo decennio. Visto il bacino di
utenza così grande e l’arricchimento giornaliero dei mercati delle app, Android ha fatto
della sicurezza uno dei suoi obiettivi principali. La sicurezza è gestita sotto tutti e tre gli
aspetti che essa concerne: evitare che un’app danneggi il sistema operativo, evitare che
un’app danneggi un’altra app ma soprattutto evitare che un’app arrechi danni o diffonda i
dati dell’utente [1], [2], [3], [7].
7
Capitolo 2: Android Security Framework
Il modello di sicurezza proposto da Android è in gran parte ereditato dal modello di
sicurezza del sistema operativo Linux, tuttavia è stata fatta qualche modifica per adattarlo
alle esigenze dei dispositivi mobili. Il concetto fondamentale della sicurezza del sistema
operativo Linux è il totale isolamento dei processi e delle relative risorse; in altre parole i
processi sono tutti identificati da un numero intero (da 0 a 65535) chiamato UID - User ID
e quindi sono logicamente separati gli uni dagli altri, stesso discorso vale per le risorse
personali di ogni processo le quali oltre ad essere separate sono anche inaccessibili
dall’esterno. Android isola i processi e le risorse a guisa di Linux ma assegna gli
identificativi differentemente, infatti essendo Linux un sistema operativo per desktop
assegna gli UID sia ad utenti fisici sia ai system services. Poiché Android è progettato per
dispositivi mobili personali non c’è alcun bisogno di assegnare più di un UID per l’utente
fisico, perciò gli UID sono assegnati alle applicazioni.
Sebbene l’isolamento dei processi sia un caposaldo della sicurezza di Android, affinché il
sistema operativo possa essere di una qualche utilità i processi devono comunicare fra
loro. Le comunicazioni sono gestite dall’Androidismo Binder che è un meccanismo di IPC
– Inter Process Communication, esso è stato progettato per un sistema operativo mobile e
quindi diversamente dal meccanismo di IPC System V non prevede strutture come:
semafori, code di messaggi e segmenti di memoria condivisa. La gestione delle
comunicazioni è quindi affidata interamente allo strato kernel, il quale mette a
disposizione un’interfaccia utile all’interazione tra processi. Questa interfaccia è il device
/dev/binder il quale è implementato dal driver del Binder. Tutte le comunicazioni passano
8
per il driver del Binder il quale gestisce una parte read-only dello spazio di indirizzamento
di ogni processo. Questo driver ha un’unica chiamata di sistema utilizzata sia per inviare
messaggi sia per riceverli, la ioctl(), che utilizza una struttura dati chiamata
binder_write_read. La struttura ha due buffer: write_buffer per la scrittura e read_buffer
per la lettura. La sequenza di comunicazione fra due processi è la seguente:
Il kernel si accorge che il processo A vuole comunicare con il processo B ed alloca nella
memoria a sola lettura di B lo spazio che andrà ad occupare con il messaggio che A
desidera inviare. Dopo il kernel notifica al processo B la locazione di memoria occupata
dal messaggio, una volta che il messaggio è stato letto e le eventuali richieste processate il
processo B notificherà al kernel di ripulire la locazione di memoria utilizzata.
La sicurezza dell’IPC è garantita dall’automatica scrittura del PID (personal ID) e del
EUID (Effective UID) del processo A nel messaggio da inviare, così facendo il processo B
può decidere se eseguire o meno i compiti che gli sono stati richiesti dal processo A.
Poiché è lo stesso kernel a scrivere nel messaggio il PID e l’EUID del processo chiamante,
quest’ultimo non può in alcun modo ottenere privilegi non consentitigli.
9
Gli altri aspetti principali della sicurezza in Android sono riassumibili nei seguenti
argomenti:
-
Application Sandboxing.
-
Gestione dei permessi.
-
SEAndroid.
-
Firma dei package.
2.1 Sandboxing
L’application sandboxing è stato progettato con la duplice intenzione di evitare sia che le
applicazioni consumino tutte le risorse del sistema operativo a discapito delle altre, sia che
le stesse applicazioni abbiano piena ed incontrollata libertà di interagire tra loro. Lo strato
del kernel Linux applica il sandboxing sia per le applicazioni normali che per i system
service.
All’atto dell’installazione di una nuova app, Android automaticamente gli
assegna un UID univoco; l’esecuzione dell’applicazione avviene poi all’interno di un
processo che gira con il medesimo UID. Inoltre ogni applicazione possiede uno spazio di
memoria personale la cui lettura e scrittura è permessa solo al proprietario. In questo modo
un’app è totalmente isolata (sandboxed) dalle altre.
10
Gli UID sono generati ed assegnati seguendo un determinato criterio, in generale l’UID
rispecchia anche i privilegi concessi all’applicazione o al system service. Se un system
service ha come UID 0 esso avrà privilegi da root user, cioè avrà tutti i privilegi possibili,
tuttavia sono pochi i daemons ad avere questo grado. Per la maggior parte dei system
service gli UID partono da 1000, questo numero sta ad indicare il system user
(AID_SYSTEM) il quale ha accesso ad un gran numero di privilegi ma ha comunque delle
limitazioni. Invece gli UID generati per per le normali app partono dal numero 10000
(AID_APP). Ogni app ha un username simbolico scritto nella forma app_XXX , le tre X
rappresentano lo scostamento dell’UID dell’app da quello dell’AID_APP. Per esempio, se
c’è un’app con username app_37 l’UID corrispondente sarà AID_APP + 37 = 10037.
L’username simbolico dell’app è anche usato per dare il nome alla directory dei dati
personali dell’applicazione, la directory si trova nel percorso /data/data.
Android dà la possibilità alle applicazioni che sono strettamente accoppiate, cioè quelle
che hanno bisogno di comunicare di frequente e di accedere alle stesse risorse, di essere
installate con lo stesso UID. Questo UID prende il nome di shared user ID e permette alle
applicazioni di essere eseguite all’interno dello stesso processo. I presupposti per poter
utilizzare lo shared user ID sono due: le app richiedenti devono essere firmate con la stessa
chiave e devono richiedere lo shared user ID a tempo di installazione poiché Android non
permette di cambiare UID una volta che l’app è stata installata. Molte app di sistema
utilizzano lo shared user ID mentre questo comportamento per le app comuni è raro e
sconsigliato [3], [7], [8], [9].
2.2 Permessi Linux e capabilities
Per capire come Android coniuga il bisogno delle applicazioni di comunicare fra loro
attraverso l’IPC e la necessità del sistema operativo di isolare tutti i processi è necessario
capire come avviene la gestione dei permessi in Linux e le sue capabilities.
Fondamentalmente in Linux ad ogni file è associata una tripla di permessi e, se qualche
processo richiede un’operazione sul file, il kernel controlla se quel processo ha il diritto
per eseguire quell’operazione. All’atto di creazione di un file esso ha un solo proprietario
(colui che crea il file) ed un solo gruppo proprietario. È possibile fare tre tipi di operazione
su di un file: lo si può leggere ( r ), lo si può scrivere ( w ) e lo si può eseguire se il file è
11
eseguibile ( x ).
Linux permette di specificare quali di queste tre operazioni può eseguire: il proprietario, il
gruppo proprietario e tutti gli altri.
Per vedere i permessi di un file in Linux è sufficiente usare il comando ls –l seguito dal
nome del file, il risultato sarà una stringa di caratteri simile a questa:
-rwxr-x--- 1 username group date hour name
La prima linea indica che il file è un file normale. Se fosse stata una cartella ci sarebbe
stata la lettera d. I primi tre caratteri rwx indicano che l’utente proprietario username può
leggere, scrivere ed eseguire il file, i seguenti tre caratteri r-x indicano che il gruppo
proprietario group può solo leggere ed eseguire il file, gli ultimi tre caratteri --- indicano
che tutti gli altri utenti non possono eseguire alcuna operazione sul file.
Le operazioni che possono essere richieste ad una cartella sono le stesse ma il significato è
differente da quello dei file normali. Avere il permesso di leggere una cartella vuol dire
poter vedere la lista dei file che essa contiene. Avere il permesso di scrivere una cartella
significa che un utente può aggiungere o eliminare file dalla cartella. Poter eseguire una
cartella significa poter accedere a tutti i file che essa contiene. In aggiunta ai normali
permessi alcune directory in Linux hanno un grado di protezione supplementare, lo sticky
bit. Lo sticky bit è un bit che, se è alto, permette l’eliminazione di un file dalla directory
solo al proprietario del file stesso, ovviamente il proprietario del file per poterlo eliminare
deve possedere anche il permesso di write.
Quindi il controllo che esegue il kernel è un semplice confronto tra l’operazione richiesta
dall’utente ed i bit di permesso associati alla categoria in cui ricade l’utente, l’utente root
può sempre eseguire qualsiasi operazione.
Possiamo quindi suddividere gli utenti in due macrocategorie: gli utenti non privilegiati
(UID diverso da 0) o normali e gli utenti privilegiati o root (UID = 0); i primi hanno
capacità molto limitate e sono soggetti ai controlli da parte del kernel, mentre i secondi
hanno la capacità di superare ogni controllo. Spesso capita che un utente normale debba
eseguire un’operazione permessa solo ad utenti privilegiati. Affinché l’utente possa
svolgere il proprio compito gli si potrebbero affidare i privilegi di root, ma ciò porterebbe
12
ad una situazione incredibilmente pericolosa giacché potrebbero verificarsi molteplici
abusi di sistema causati dall’utilizzo improprio di tutti i privilegi. È necessaria quindi una
via di mezzo che permetta all’utente normale di ottenere soltanto un numero ristretto di
privilegi, corrispondenti all’operazione che deve eseguire. Gli sviluppatori del kernel
Linux hanno così creato le Posix capabilities. Le capabilities sono disposte in tre bitmap:
l’inheritable (I), la permitted (P) e la effective (E); ogni capability è rappresentata da un bit
in queste bitmap. Se un processo vuole eseguire un’operazione che richiede privilegi root
allora il kernel controlla nelle bitmap se il bit della capability relativo all’operazione
richiesta è alto oppure no. La bitmap Inheritable contiene le capabilities che possono
essere ereditate da un programma che è eseguito dal processo. La bitmap Permitted mostra
le capabilities che possono essere utilizzate dal processo, mentre la bitmap Effective
mostra le capabilities usate attualmente dal processo. Una lista commentata di tutte le
capabilities esistenti in Linux è presente in usr/src/linux/include/linux/capability.h [10].
2.3 Permessi Android
La soluzione trovata dagli sviluppatori del kernel Linux per assegnare solo determinati
privilegi a processi non root è alla base della gestione dei permessi in Android. L’idea
fondamentale è la stessa ma i meccanismi con i quali essa è applicata sono diversi poiché
sono stati adattati ad un sistema operativo mobile.
Le applicazioni di Android per espandere le proprie funzionalità o per eseguire i propri
compiti sono in grado di richiedere un set di permessi che consente loro di avere
determinati privilegi. Questi permessi sono delle stringhe di caratteri e se accordati
possono garantire l’utilizzo delle risorse hardware, delle risorse del sistema operativo e dei
dati delle altre app. Il rilascio dei permessi avviene a tempo di installazione ed una volta
che sono stati accordati essi sono validi per tutta la vita dell’app. I permessi si dividono in
due categorie: quelli preinstallati e quelli personalizzati. Il numero dei permessi
preinstallati disponibili cresce con l’arricchimento delle funzionalità di base presenti nelle
versioni recenti di Android, una lista aggiornata è disponibile all’indirizzo ufficiale degli
13
sviluppatori: http://developer.android.com/reference/android/Manifest.permission.html
Si possono conoscere i permessi anche operarando da terminale attraverso il comando
pm list permissions.
Tutti i permessi sono definiti all’interno del package android e sono scritti nella seguente
forma: permission:android.permission.PERMISSION_NAME.
Un’app richiede al sistema operativo uno o più permessi attraverso un file chiamato
AndroidManifest.xml usando il tag <uses-permissions>.
Ad esempio un’app che richiede il permesso per utilizzare internet userà il tag in questo
modo: <uses-permission android:name=”android.permission.INTERNET”/>.
La gestione dei permessi è operata dal system service package manager il quale gestisce
tutte le informazioni sui package installati, ad esempio: versione, percorso di installazione,
permessi rilasciati e certificato. Se l’app subisce un update o viene disinstallata il package
manager aggiorna le informazioni disponibili, queste ultime sono memorizzate in un file
XML collocato nel percorso data/system/packages.xml.
Android non pone i permessi tutti sullo stesso piano infatti esistono quattro livelli di
protezione ed ogni permesso appartiene ad un solo livello. Ogni livello indica sia il rischio
che può comportare il rilascio del permesso sia il criterio da adottare per decidere se
rilasciare o meno il permesso ad un’app.
Normal. È il livello di protezione di base, i permessi che rientrano in questa categoria sono
quelli a rischio minimo. Il rilascio di questo permesso avviene in maniera automatica e
trasparente all’utente.
Dangerous. È il livello di protezione i cui permessi possono costituire un pericolo per il
sistema operativo o per le altre applicazioni. In genere i permessi richiedono la gestione
dei dati utente o il controllo di risorse hardware. Il rilascio dei permessi avviene solo se
l’utente, all’atto dell’installazione e attraverso una schermata, accetta tutte quante le
richieste. Android non permette di accettare solo una parte dei permessi, infatti vige la
regola del tutto o niente cioè o i permessi sono tutti rilasciati oppure l’app non viene
installata.
Signature. È un livello di protezione esclusivo, i permessi che ricadono in questa categoria
14
possono essere rilasciati solo alle applicazioni firmate con la stessa chiave crittografica
dell’applicazione che ha dichiarato il permesso. Questa condizione è molto stringente
poiché la chiave è posseduta solo dal proprietario dell’app o della piattaforma.
SignatureOrSystem. È un livello di protezione esclusivo i cui permessi possono essere
richiesti solo dalle app che sono firmate con la stessa chiave crittografica del possessore
dell’app o dalle applicazioni che fanno parte dell’immagine del sistema.
Dopo che l’applicazione ha ricevuto tutti i permessi richiesti bisogna memorizzare quali
permessi sono stati rilasciati per quell’app così da permettergli di funzionare, per fare ciò
si utilizza il concetto di gruppo visto in Linux.
All’atto di installazione l’app riceve un UID e viene eseguita in un processo che avrà lo
stesso UID, un GID e diversi GID supplementari.
In Android, l’appartenenza di un’applicazione ad uno o più gruppi è resa esplicita dal
possesso dei GID. Questo meccanismo consente di restringere l’accesso alle risorse
hardware o di sistema operativo solo a chi appartiene ad un determinato gruppo e cioè solo
alle applicazioni che hanno ricevuto il relativo permesso. Un file che contiene le
associazioni
tra
gruppi
e
permessi
built-in
è
presente
nel
percorso
etc/permission/platform.xml.
Ad esempio tutte le app che hanno ricevuto il permesso per utilizzare connessioni internet
apparterranno al gruppo inet.
<permission name=”android.permission.INTERNET”>
<group gid=”inet” />
</permission>
In Linux le connessioni di rete possono essere create da tutti i processi, in Android invece
ciò è stato reso possibile solo per un ristretto gruppo di processi. Limitare l’uso delle
connessioni di rete fa parte del meccanismo di controllo, applicato dal kernel, noto come
Paranoid Networking. Il Paranoid Networking controlla non solo la creazione di socket di
rete di natura IPv4, ma anche di natura IPv6 e Bluetooth.
15
Lo strato di Application Framework si occupa di controllare che un processo chiamante
abbia tutti i permessi necessari per poter utilizzare le risorse che sta chiedendo. Il controllo
può essere di due tipi: dinamico o statico.
Il controllo dinamico sfrutta il fatto che ogni UID è associato ad un solo package ed il
system service package manager gestisce un database aggiornato di tutti i permessi
rilasciati ad ogni package. Android per semplificare le operazioni di controllo, giacché
sono molto frequenti, mette a disposizione una classe che possiede metodi funzionali a
questi controlli, android.content.Context è il nome della classe. Il metodo più importante
della classe è: int Context.checkPermission(String permission, int pid, int uid), il cui
compito è di restituire il valore PERMISSION_GRANTED se il controllo va buon fine
mentre deve restituire il valore PERMISSION_DENIED se il processo chiamante non ha i
permessi necessari. Tutti i processi chiamanti di grado root o system ottengono
direttamente il valore PERMISSION_GRANTED, così come se il processo chiamante è lo
stesso che ha dichiarato il permesso. Se invece è un normale processo a chiedere la risorsa
vengono effettuati due controlli: il primo controllo mira ad identificare se la risorsa
richiesta è pubblica o privata, se la risorsa è privata allora si restituisce il valore
PERMISSION_DENIED; il secondo avviene solo se la risorsa è pubblica, in questo caso il
package manager risale all’app partendo dall’UID e controlla nel database il file che
contiene tutti i permessi accordati all’app. Se il permesso necessario è fra quelli rilasciati
allora si ha il ritorno del valore PERMISSION_GRANTED, altrimenti si ha il caso duale.
Il controllo statico ha luogo quando un’app cerca di utilizzare un metodo o una risorsa di
un’altra app e per fare ciò l’app chiamante deve aver ottenuto un permesso specifico.
Android tramite il meccanismo degli intenti dà la possibilità al processo chiamante di
scegliere se il componente cercato deve essere di un’app ben specifica (explicit intent)
oppure di un’app generica (implicit intent), l’ultima opzione fa sì che stesso Android
cerchi un componente soddisfacente i criteri e se ne viene trovato più di uno viene
mostrata all’utente una finestra di selezione. Il processo di controllo prevede che vengano
ottenuti sia il PID che l’UID del processo chiamante attraverso le system call
16
Binder.getCallingUid() e Binfer.getCallingPid(). Ancora una volta si sfrutta l’associazione
univoca tra UID e package e si ricorre al file del database che contiene le informazioni sui
permessi rilasciati, se il permesso necessario è presente allora la chiamata va a buon fine
altrimenti viene lanciata un’eccezione. Il system service che effettua il controllo è
l’activity manager.
Con l’introduzione della versione 6.0 di Android, chiamata M, la gestione dei permessi ha
subito una sostanziale modifica. Non sarà più necessario rilasciare i permessi a tempo di
installazione, infatti le app saranno installate automaticamente ed i permessi necessari
saranno autorizzati solo a tempo di esecuzione quando sarà necessario utilizzare la relativa
funzionalità [2], [3], [7].
2.4 SELinux e SEAndroid
La sicurezza di Android si basa su due aspetti fondamentali ereditati dalla cultura di
Linux: l’application sandbox e la gestione dei permessi, queste due tecniche fanno
riferimento al meccanismo di sicurezza noto come DAC – Discretionary Access Control.
In senso generale si controlla l’accesso ad una risorsa basandosi sull’identità di chi lo
richiede o dalla sua appartenenza ad un gruppo, la discrezionalità giace nel fatto che un
soggetto che possiede il permesso può passarlo ad un altro soggetto anche in maniera
involontaria. Questo passaggio di permessi clandestino renderebbe vano il meccanismo di
protezione fornito dal sandboxing e dalla gestione dei permessi, inoltre il fatto che un
processo root disponga di privilegi illimitati e non separati come accade nelle capabilities
di Linux rende Android suscettibile ad abusi da parte di processi che hanno ottenuto il
grado root attraverso un exploit. Per contrastare queste problematiche è stato progettato un
nuovo meccanismo di sicurezza chiamato MAC – Mandatory Access Control
implementato in SELinux e recentemente anche in SEAndroid. Security Enhanced Linux è
un modulo di sicurezza che fa parte di una framework chiamata Linux Security Modules,
tutti i moduli che fanno parte di questa framework migliorano il controllo degli accessi in
Linux.
Esistono due tipi di MAC: Type Enforcement e Multi-Level Security, SELinux li supporta
17
entrambi ma verrà trattato in questo elaborato solo il primo tipo, poiché Android non
contempla il secondo. L’architettura di SELinux può essere schematizzata come un
insieme di quattro componenti: il manager degli oggetti (OM), un vettore di accessi cache
(AVC), un server di sicurezza e una politica di sicurezza. I primi tre componenti risiedono
nel kernel Linux mentre l’ultimo è parte dello spazio utente. La sequenza di azioni che
avvengono se un processo chiede una determinata risorsa è la seguente:
il processo chiede di effettuare un’azione su di un oggetto, il manager dell’oggetto in
questione chiede al vettore degli accessi se il processo ha fatto una richiesta lecita. L’AVC
tiene in memoria le decisioni di sicurezza già prese e se quella relativa al nostro caso è
presente in lista allora egli risponde all’OM con la decisione. Se la decisione non è
presente nella lista allora l’AVC deve contattare il security server il quale è l’entità
preposta a prendere una decisione in base alla politica di sicurezza stabilita. Dopo aver
preso la decisione il security server la invia all’AVC il quale prima la memorizza e poi la
invia all’OM. Infine l’OM permette o nega l’azione in funzione del responso.
Affinché una decisione possa essere presa, sia i soggetti richiedenti che gli oggetti richiesti
sono dotati di un insieme di quattro attributi di sicurezza noto come security context, gli
attributi sono: username, role, type e range. Gli username sono usati in genere per
identificare un gruppo di utenti, ogni utente possiede almeno un ruolo che gli permette di
accedere a determinati oggetti associati ad un tipo, il tipo serve per raggruppare i processi
in un dominio (in questo caso prende il nome di dominio) o gli oggetti in una logica. Il
campo range invece nel Type Enforcement è riempito da una costante poiché è necessario
solo per il MLS.
Il security context deve essere prima assegnato e poi memorizzato. Gli oggetti sono visti
come file, la memorizzazione avviene in un campo dei metadati del file mentre
l’assegnazione dei campi del security context può avvenire in due modi: esplicitamente
attraverso l’inizializzazione dell’oggetto o implicitamente attraverso l’ereditarietà.
L’oggetto figlio quindi riceve lo stesso contesto dell’oggetto padre e se la politica di
sicurezza lo permette egli può cambiare il proprio contesto in un secondo momento. Per i
soggetti, perlopiù processi, l’assegnazione del security context avviene in maniera analoga
18
alle modalità degli oggetti.
Le decisioni sull’accesso ad un oggetto kernel da parte di un processo sono prese dal
security server; esse sono ponderate sulla base della politica di sicurezza vigente. Le
politiche di sicurezza sono implementate in un linguaggio apposito formato da statements
e rules: gli statement definiscono i tipi, i ruoli e gli utenti mentre le rules definiscono il
permesso o il divieto di accesso ad una risorsa.
SELinux si può presentare in tre stati: disabilitato, permissive ed enforcing. Il primo stato
non prevede alcuna applicazione del meccanismo MAC, quando SELinux è disabilitato
infatti il DAC è operativo. Lo stato permissive fa sì che la politica sia caricata ed i
controlli sugli oggetti vengano effettuati ma il rifiuto di fornire l’accesso ad un soggetto
non conforme è solo notificato tramite un messaggio. Infine nello stato Enforcing la
politica è sia caricata che applicata.
L’implementazione del meccanismo MAC in Android è una conseguenza naturale del
fatto che sia quest’ultimo che Linux condividono lo stesso kernel, seppur con qualche
differenza. Proprio a causa di queste differenze non è stato possibile applicare SELinux ad
Android e si quindi venuti alla creazione di un meccanismo adatto al sistema operativo
mobile noto come SEAndroid.
Per implementare SEAndroid sono stati necessari dei cambiamenti sia a livello kernel sia a
livello userspace. A livello kernel sono state fatte delle modifiche affinché il Binder IPC
potesse supportare le funzioni dei Linux Security Modules. A livello userspace invece è
stato introdotto il labelling per il nucleo della libreria C e i daemons nativi insieme
all’application framework sono stati resi adatti a SEAndroid.
Allo start-up di Android tutti i processi di sistema sono inizializzati a partire dal primo
processo che viene eseguito, init. Questo processo carica la politica di sicurezza contenuta
nella directory /sepolicy e poi setta il modo in cui SEAndroid dovrà operare: enforcing,
permissive o disable. La scelta su come applicare la sicurezza è presa in base al valore di
ro.boot.selinux, il valore di questo campo varia a sua volta a seconda del contenuto del
campo androidboot.selinux il quale è modificato tramite linea di comando.
Come in SELinux, anche in SEAndroid i security context sono salvati negli attributi estesi
19
del relativo file. Tuttavia SEAndroid mantiene una corrispondenza tra il path dell’oggetto
salvato e il suo security context nel file chiamato file_contexts.
Android usa alcune proprietà di sistema a visibilità globale per informare i vari processi
sullo stato dell’hardware, dei servizi o delle risorse. Queste proprietà sono ovviamente
disponibili solo in lettura ai processi comuni, la scrittura è riservata ai processi con
privilegi root, system o radio. SEAndroid aggiunge un livello di protezione MAC a questo
meccanismo facendo sì che solo i processi appartenenti ad un determinato dominio
possano modificare determinate proprietà. A questo proposito si fornisce un security
context ad ogni proprietà di sistema e si salva la corrispondenza in un file apposito,
chiamato property_context.
Il processo zygote è colui che setta le credenziali DAC (UID, GID e GID supplementari)
per ogni processo che genera, SEAndroid ha introdotto in zygote il controllo e
l’assegnazione dei security context per ognuno dei processi. Il modo attraverso cui zygote
genera il security context è il file di configurazione seapp_contexts il quale contiene delle
regole di assegnazione universali. Confrontando le proprietà del processo con le regole
presenti nel file, zygote riesce a dettagliare il security context.
Il meccanismo di sicurezza MAC previsto da SEAndroid è disponibile a partire dalla
versione 4.0 di Android Ice Cream Sandwich ma solo in modalità permissive, dalla
versione 4.4 KitKat invece è disponibile anche in modalità enforcing.
SEAndroid però non è solo una prerogativa dello strato kernel, infatti gli sviluppatori
hanno deciso che il meccanismo MAC può essere applicato anche allo strato Middleware.
Il concetto di Middleware MAC mira ad espandere la sicurezza che SEAndroid può
fornire a tempo di installazione, infatti nonostante la volontà dell’utente di rilasciare i
permessi necessari per installare un’app, il Middleware MAC ne può impedire il rilascio
effettivo sulla base del certificato dell’app e sul nome del relativo package [6], [7].
2.5 Firma dei package
In ambito della sicurezza la firma del codice è una strategia usata per assicurare due
concetti: l’autenticità e l’integrità. Il codice è autentico se è possibile far corrispondere il
20
reale creatore del codice con l’entità che afferma di averlo creato. Il codice è integro se
esso non è stato alterato in alcun modo. Il creatore per dimostrare queste cose deve
possedere una chiave di firma, unica e personale, la cui verifica da parte dell’utilizzatore
del prodotto mira a verificare che il codice sia stato firmato con la chiave attesa. Questa
tecnica non può essere adoperata per constatare se il codice è malevolo oppure no.
Android controlla i propri package attraverso la verifica della relativa firma, sia per
garantire i due aspetti citati prima ma anche per rilasciare i permessi di livello signature.
I package di Android sono distribuiti sotto forma di file APK la cui estensione è .apk , è
possibile esplorare il contenuto di questi package giacché essi non sono altro che
un’estensione
del
formato
.jar
e
quindi
indirettamente
del
formato
.zip.
Fondamentalmente, questi package contengono: il codice eseguibile, le risorse associate, il
file AndroidManifest.xml e la firma. La firma è contenuta nella directory nota come
META-INF.
In Android la firma del codice è simile a quella usata in Java infatti usa la crittografia a
chiave pubblica ed il certificato X.509. In molti ambienti la firma del codice deve essere
emessa da una CA – Certificate Authority la quale è fonte di fiducia. Tuttavia in Android
non è necessario ricorrere alla CA per firmare il codice poiché non è possibile trovare un
certificato che sia valido ed accettato da tutte le aziende che usano Android, a questo
proposito è stata resa disponibile l’autocertificazione.
Per firmare il codice o per verificarlo è possibile usare lo strumento di firma del codice
disponibile nella JDK jarsigner oppure il tool di Android signapk.
Per firmare con jarsigner basta usare il comando jarsigner dalla linea di comando
specificando: il keystore file, l’alias della chiave usata per firmare e l’algoritmo di firma.
$ jarsigner –keystore debug.keystore –sigalg SHA1withRSA test.apk androiddebugkey
Le versioni di Android precedenti alla 4.3 supportano solo l’algoritmo di firma
SHA1withRSA, mentre dalla versione 4.3 in poi si può utilizzare anche SHA256withRSA
e SHA512withRSA.
Per usare jarsigner per verificare il package si usa il comando seguente :
$ jarsigner –keystore debug.keystore –verify –verbose –certs test.apk
21
Prima viene eseguito il controllo del blocco firmato e del certificato di firma infine si
controlla che i digest appartenti al CERT.SF corrispondano ai relativi blocchi del
MANIFEST.MF.
Signapk ha bisogno di due ingressi per firmare il package : la chiave di firma ed il file
certificato.
$ java –jar signapk.jar cert.cer key.pk8 test.apk test-signed.apk
Signapk dà anche la possibilità di firmare un intero file per proteggere gli aggiornamenti
fatti OTA- Over The Air, può essere utilizzata inserendo il comando –w [7].
22
Capitolo 3: Sicurezza del dispositivo fisico
La sicurezza di Android non contempla solo i processi, le risorse di sistema e le varie
interazioni fra di esse, ma abbraccia anche tutto ciò che riguarda la sicurezza dell’handset
in sé. La protezione dei dati personali, dell’accesso al dispositivo e dell’hardware sono le
tematiche che più coinvolgono gli utenti di Android interessati alla salvaguardia del
proprio dispositivo; gli sviluppatori del sistema operativo mobile affrontano con grande
attenzione questi aspetti ed a questo proposito aggiungono migliorie alle precedenti
funzionalità e ne introducono di recenti ad ogni nuova versione.
3.1 Boot
All’accensione del dispositivo l’utente vede in genere comparire per alcuni secondi sul
display il logo di Android oppure il logo del brand dell’handset, il tempo usato per
mostrare una delle due immagini è il tempo necessario al dispositivo per eseguire la fase di
booting o bootloading. In realtà questa fase è composta da più fasi, ognuna delle quali
svolge un compito ben specifico, tuttavia possiamo tranquillamente considerarla come
unica giacché il numero di fasi del booting varia a seconda del costruttore dell’hardware. I
compiti del booting sono: inizializzare l’hardware del dispositivo e caricare il sistema
operativo nella memoria RAM e se possibile disporre un’interfaccia utente.
Questa fase è soggetta ad alcuni meccanismi di protezione, infatti è possibile usufruire di
alcune vulnerabilità per far caricare un sistema operativo diverso da quello usuale che dia
l’accesso ai dati personali dell’utente. È anche possibile sfruttare il modo in cui avvengono
gli aggiornamenti per eliminare i controlli di sicurezza presenti sui dati utente.
23
Nonostante le diversità dei vari processi di booting, ognuna di essa dà la possibilità,
tramite la pressione simultanea di un insieme di tasti o attraverso la linea di comando
dell’ADB - Android Debug Bridge, di entrare in download mode e di eseguire la scrittura
di un file immagine sul disco rigido. Per evitare che il dispositivo venga violato entrando
in download mode e caricando un sistema operativo ad hoc si è soliti usare un bootloader
bloccato il quale impedisce che vengano scritti sul disco rigido file immagine oppure
permette la scrittura solo ai file immagine dotati di una firma valida. È possibile sbloccare
il bootloader ma il prezzo da pagare è dover formattare tutti i dati utente così da prevenire
una violazione dei dati personali in caso venisse montato un sistema operativo malevolo.
Attraverso la pressione di un’altra combinazione di tasti è possibile entrare in recovery, un
sistema operativo mobile minimale usato per installare gli aggiornamenti OTA. Gli
aggiornamenti OTA sono firmati con la chiave privata del costruttore e per assicurare
l’integrità e l’autenticità il recovery esegue il controllo degli aggiornamenti attraverso la
chiave pubblica. Il recovery può essere sostituito da un recovery sviluppato da terze parti,
generalmente lo si fa per installare una versione di Android customizzata. L’insidia
nascosta in questa pratica è che può permettere l’accesso al dispositivo con privilegi di
root attraverso l’uso dell’ADB. Crittografare i file può essere inutile giacché attraverso
l’uso di un rootkit si può aggirare la cifratura. È stato previsto quindi di usare un boot
verificato al fine di evitare violazioni derivanti da questa tecnica, questo meccanismo
prevede l’impiego di un utility del kernel chiamata device mapper la quale effettua una
corrispondenza uno ad uno oppure uno a molti tra blocchi virtuali e blocchi fisici del
dispositivo e poi ne verifica l’integrità. Se si usa device mapper usando dm-crypt i blocchi
vengono automaticamente decriptati in lettura e criptati in scrittura. La lettura di un blocco
è permessa solo se il controllo di integrità effettuato da device mapper ha avuto successo,
se altrimenti il blocco è stato corrotto dal rootkit che l’ha modificato, viene generato un
errore di sistema e la lettura viene impedita [4], [7].
24
3.2 Crittografia
I dati personali dell’utente rappresentano nella maggior parte dei casi l’obiettivo primario
di un attacco da parte di malintenzionato. Android offre diversi meccanismi di sicurezza
affinché l’attacco venga sventato ed uno dei pilastri fondamentali è la cifratura dei dati.
Cifrare i dati è una tecnica molto antica che consiste nel convertire il testo in chiaro in un
testo cifrato usando un schema di cifratura noto solo al proprietario dei dati.
Android implementa questa funzionalità attraverso la Full Disk Encryption - FDE cioè
tutto ciò che è presente sul disco rigido nella partizione userdata è criptato, solo una
piccola parte del sistema operativo viene lasciata in chiaro ed è la parte in cui è
memorizzata la chiave di decifratura attraverso la quale è possibile decriptare i file. Questa
chiave di decifratura però è un componente sensibile del meccanismo e perciò va cifrata
anch’essa attraverso una chiave di cifratura di chiave nota come KEK – Key Encryption
Key. La KEK è mantenuta separata in un blocco hardware oppure è derivata da una
password inserita dall’utente. Come scritto in precedenza il modulo attraverso cui è
possibile criptare i dati è dm-crypt, esso usa una chiave crittografica casuale a 128 bit
insieme al sistema AES - Advanced Encryption Standard nella modalità CBC. Il problema
di questa tecnica crittografica è che essa necessita di una sequenza di bit generata in modo
casuale nota come IV – Initialization Vector, essendo la memoria acceduta in maniera non
sequenziale è quindi necessario generare tante sequenze quanti sono i blocchi criptati.
Android affronta la situazione usando il vettore ESSIV – Encrypted Salt Selector IV e
l’algoritmo di hashing SHA-256. L’algoritmo SHA-256 è usato dall’ESSIV per generare
una chiave secondaria, nota come salt, a partire dalla chiave di crittazione del disco. La
chiave salt è poi usata come chiave crittografica per criptare i numeri di settore di ogni
blocco, il risultato di ciascuna operazione di crittazione è l’IV, generato casualmente, del
relativo settore.
Per cifrare la chiave di decifratura attraverso la KEK è possibile utilizzare una password
immessa dall’utente. Android ha utilizzato a lungo l’algoritmo di derivazione PBKDF2
per generare una chiave crittografica a partire da una password, quest’ultimo utilizza una
sequenza casuale di 128 bit e solo 2000 iterazioni. Un numero così basso di iterazioni per
25
generare una chiave crittografica è diventato un ostacolo alla sicurezza della chiave
giacché attraverso tecniche di brute force che impiegano il multi core e le GPU di un
calcolatore è possibile trovare la chiave in un lasso di tempo ragionevole.
Per ovviare a questo problema gli sviluppatori di Android a partire dalla versione 4.4
KitKat hanno introdotto un nuovo metodo di cifratura noto come script il quale impiega
un numero molto più elevato di iterazioni e tende a saturare la memoria fisica dei
calcolatori che impiegano tecniche di brute force [7].
3.3 Screen lock
Lo screen locking è un meccanismo di sicurezza che mira ad evitare che una persona non
autorizzata acceda all’interfaccia utente del dispositivo in maniera incontrollata; gli screen
lock non sono altro che applicazioni regolari eseguite ogni volta che il dispositivo viene
acceso oppure lo schermo viene illuminato.
Queste applicazioni sono delle viste appartenenti ad una classe contenitore chiamata
KeyguardHostView, che invoca di volta in volta il metodo di screen lock impostato e
memorizza le password selezionate, il controllo delle password è effettuato dalla classe
LockPatternUtils. Android ad oggi prevede cinque metodi di screen lock: slide, face
unlock, pattern unlock e pin/password.
Il metodo slide è equivalente a nessuna protezione, infatti l’applicazione dedicata mostra
solo una schermata il cui sblocco è possibile trascinando il dito verso destra o sinistra.
Il metodo face unlock fa parte della sicurezza biometrica ed è disponibile solo per i
dispositivi provvisti di una fotocamera frontale, attraverso quest’ultima è possibile
mostrare il viso dell’utente all’applicazione integrata di rilievo facciale. Sebbene questo
metodo possa sembrare sicuro in realtà esso non lo è affatto giacché il controllo fallisce in
caso di luce non sufficiente, ad ogni modo questo metodo necessita di uno degli altri
metodi di sblocco in caso non sia possibile usarlo.
Il metodo del pattern unlock prevede che l’utente digiti una sequenza di punti attraverso
l’uso di una matrice 3x3, la sequenza per essere valida deve essere maggiore di tre punti
ed inferiore a dieci punti, inoltre non deve contenere ripetizioni. Ad ogni punto è associato
26
un numero: 0 è associato al punto in alto a sinistra e 8 al punto in basso a destra, questa
associazione rende il pattern simile ad un pin tuttavia l’esclusione delle ripetizioni fa sì
che il pattern sia molto più semplice. Il pattern selezionato viene salvato dal metodo
saveLockPattern() della classe LockScreenUtils che ne salva l’hash e lo ripone nella
directory di sistema /data/system/gesture.key. L’hash dei pattern però non viene generato
usando sequenze casuali e ciò rende gli hash delle varie sequenze tutti uguali per ogni
dispositivo, online sono disponibile delle tabelle che associano ad ogni hash la rispettiva
sequenza.
Ciò che rende il pattern unlock un metodo non sicuro è una tecnica di
ingegneria sociale chiamata smudge attack, questa tecnica sfrutta la striscia lasciata dal
dito sul touch screen per discernere il pattern di sblocco.
I metodi pin/password unlock sono simili e quindi possono essere trattati insieme, viene
chiesto all’utente di inserire un pin o una password di cui ne sarà calcolato l’hash
combinando gli hash di SHA-1 e MD5 con un valore casuale a 64 bit. L’hash viene poi
salvato
in
una
directory
di
sistema,
/data/misc/password.key,
dal
metodo
saveLockPassword() della classe LockPatternUtils. Il pin/password inserito viene
confrontato dal metodo checkPassword() della medesima classe [5], [7].
3.4 Sicurezza del Radio Interface Layer
Il Radio Interface Layer - RIL è lo strato costruito appositamente per gestire tutti i tipi di
comunicazione radiotelefonica disponibili: GSM, GPRS, EDGE, CDMA (3G) e LTE
(4G). Va da sé che i servizi come le telefonate, gli sms, le videochiamate ed il networking
non potrebbero esistere senza il supporto di questo strato. Ogni pacchetto dati inviato o
ricevuto passa per lo stack RIL prima di giungere a destinazione. Proprio a causa di questa
sua centralità il RIL è un obiettivo appetibile per malintenzionati, i quali se avessero
successo nei loro attacchi potrebbero spiare le comunicazioni o sfruttare le risorse
economiche della vittima. Le comunicazioni radio in Android avvengono tramite
l’interazione di due sistemi: il sistema principale ed il sistema in banda base. Il sistema
principale è quello classico rappresentato dall’architettura di Von Neumann, il sistema in
banda base invece è costituito da due blocchi correlati il primo blocco indica qual è la rete
27
di dati utilizzata (es. GSM) ed il secondo blocco invece è l’insieme di una CPU, una
memoria ed un DSP - Digital Signal Processor. I due blocchi comunicano con il sistema
principale attraverso l’uso di dispositivi UART- Universal Asynchronous Receiver
Transmitter. Lo stack può essere visto come segue:
Analizzando la struttura seguendo un approccio bottom-up, notiamo che:
il kernel di Android possiede i driver per interagire con il sistema in banda base ed allo
stesso tempo mette a disposizione un’interfaccia allo strato userspace per far sì che il suo
daemon possa disporre dei servizi necessari. Lo strato userspace possiede appunto un
daemon nativo chiamato rild ed una relativa libreria nota come vendor RIL. Lo strato di
application framework a sua volta fornisce un’interfaccia alle applicazioni dello strato
sovrastante per usufruire dei servizi del rild ed inoltre provvede a delle astrazioni utili a
28
diversificare i servizi richiesti in base alla rete utilizzata. Infine lo strato application ospita
tutte le applicazioni che sfruttano i servizi di radiotelefonia. Google chiama queste
applicazioni tracker.
È chiaro che la più importante dello stack è il daemon nativo rild, esso ha il compito di
gestire le comunicazioni tra l’application framework e l’hardware di sistema. Per svolgere
le sue mansioni il daemon allo start up carica le librerie vendor e poi crea una interfaccia
Binder verso lo strato superiore. Le API del rild devono gestire una grande varietà di
hardware pertanto la libreria possiedono un gran numero di funzioni specifiche per ciascun
componente. Il daemon possiede all’inizio della propria vita i privilegi di root, ma essendo
un componente attaccabile dall’esterno gli vengono revocati e gli sono accordati i privilegi
di rango radio.
Il protocollo con cui il rild comunica con lo strato hardware è differente da costruttore a
costruttore, quest’inclinazione verso protocolli proprietari ha portato alla possibilità di
personalizzare lo stack telefonico in modo da renderlo più adatto alle esigenze degli
sviluppatori di terze parti.
L’arma usata dagli sviluppatori di Android per prevenire gli attacchi al Radio Interface
Layer è quello di eseguire il fuzzing, cioè porre in ingresso dei dati malevoli, documentare
il comportamento del sistema e se si è in presenza di un exploit o di un malfunzionamento,
correggerlo. Il fuzzing si è rivelato molto utile in quanto dal primo rilascio di Android esso
ha permesso di scovare e correggere molti malfunzionamenti, come quello relativo al
servizio SMS [2], [4].
29
Conclusioni
L’attenzione con cui sono stati progettati i meccanismi di sicurezza del sistema operativo
Android ne fa senza dubbio uno dei sistemi informatici più sicuri disponibili attualmente
per i dispositivi mobili.1 Ogni nuova versione porta con sé innovazioni o perfezioni dei
meccanismi di sicurezza in modo tale da rendere l’esperienza dell’utilizzo sempre più
fidata. Tuttavia la cura quasi maniacale per tutti i dettagli implicati nella gestione della
sicurezza non rende Android un sistema operativo perfetto, impenetrabile oppure
infallibile. Se da un lato ci sono migliaia di uomini e donne che si impegnano a rendere
Android sempre più sicuro, dall’altro lato ci sono sempre più persone che lavorano per
sfruttare le vulnerabilità di Android a proprio favore. In mezzo a queste due categorie si
trovano gli utenti di Android i quali spesso sono ignari del lavoro di ambo le parti. Google
cerca di tutelare i suoi utenti anche attraverso la divulgazione informatica, infatti ha reso
disponibili il sito web: https://source.android.com/devices/tech/security/index.html e la
community: https://groups.google.com/forum/#!forum/android-security-discuss
affinché
gli utenti possano imparare di più sul sistema operativo mobile e possano confrontarsi
sulle varie tematiche relative alla sicurezza. Molti ricercatori convengono, ed io mi trovo
d’accordo, che bisognerebbe introdurre in Android un piccolo manuale che spieghi
all’utente quali sono le azioni da intraprendere e quali quelle da evitare per migliorare al
massimo la sicurezza del sistema operativo.
1
https://static.googleusercontent.com/media/source.android.com/it//devices/tech/security/reports/Google_Android_Secu
rity_2014_Report_Final.pdf
30
Bibliografia
[1] Sito ufficiale di Android, https://www.android.com/history/
[2]
Sito
ufficiale
di
Android
Open
source
project,
https://source.android.com/devices/tech/security/
[3] A. Tanenbaum, Modern Operating Systems 4th ed, Pearson, pp 802-850
[4] J. J. Drake, P. Oliva Fora, Z. Lanier, C. Mulliner, Stephen A. Ridley, G. Wicherski.
Android Hacker's Handbook, Riley, cap. 5, cap. 10 e cap. 11
[5] A. Gargenta, Deep Dive into Android Security, The Android Developer Conference II
[6]
Sito
di
divulgazione
su
Android,
http://seandroid.bitbucket.org/PapersandPresentations.html#3
[7] N. Elenkov, Android Security Internals, No Starch Press, 2014
[8] P. Faruki, A. Bharmal, V. Laxmi, V. Ganmoor, M. Gaur, M. Conti, M. Rajarajan,
Android Security: A Survey of Issues, Malware Penetration and Defenses, IEEE
Communications Surveys and Tutorials, January 2015
[9] Y. Zhaunirovich, Android Securty (and not) Internals, ebook gratuito
[10] M. Mitchell, J. Oldham, A. Samuel, Advanced Linux Programming, New Rider
Publishing, 2001, cap 10
31
Lista delle figure
[1]
http://jaredrummler.com/2014/11/09/lollipop-land/
[2]
Android Security Internals, pp. 2
[3]
http://www.cubrid.org/blog/dev-platform/binder-communication-mechanism-ofandroid-processes/
[4]
Deep Dive into Android Security, slide 7.
[5]
Android Hacker's Handbook, pp. 370
32