I ricercatori della californiana Armis (Palo Alto) hanno rilasciato un white paper che descrive otto vulnerabilità (per i quali sono disponibili exploit) riguardanti le implementazioni dello standard Bluetooth in Linux (e Android), Windows e iOS.
Raggruppate sotto il nome di BlueBorne (da Bluetooth e Airborne, termine che identifica gli attacchi effettuati per via aerea), sono caratterizzate da una superficie di attacco molto vasta e un impatto potenziale elevato: oltre a influenzare gran parte dei sistemi operativi presenti sul mercato, gli eventuali attacchi non richiedono interazioni con la vittima ; tali vulnerabilità, inoltre, consentono la possibile esecuzione di codice arbitrario e non sono risolvibili con modifiche alle configurazioni .
Common Vulnerability Exposure CVE-2017-1000251
Si tratta di una remote code execution su Bluez , il componente del kernel Linux che fornisce le funzionalità relative alla gestione di periferiche Bluetooth. La vulnerabilità, causata da un buffer copiato senza controllarne la dimensione nell’implementazione del livello L2CAP dello stack, colpisce le versioni più recenti del kernel (dalla 3.3-rc1 in poi) .
L2CAP è il livello di rete dello stack protocollare di Bluetooth, che offre anche funzionalità avanzate generalmente collocabili nel livello di trasporto (ad esempio la possibilità di gestire la frammentazione dei pacchetti e di gestire politiche QoS).
La comunicazione avviene su più canali logici asincroni, contrassegnati da un Channel ID, l’equivalente di un numero di porta per le connessioni TCP o UDP.
Tutti gli altri servizi (RFCOMM per le comunicazioni seriali, SDP per la discovery dei servizi nell’area circostante, OBEX per il trasferimento dei file) eccetto il servizio Audio sono costruiti sopra al layer L2CAP.
Nello stabilire una connessione L2CAP i due peer possono negoziarne i parametri mediante lo scambio di pacchetti di tipologia L2CAP_ConfReq (richiesta) e L2CAP_ConfResp (risposta) o tramite la funzionalità EFS (Extended Flow Specification).
In tal caso ciascuno dei peer effettua una validazione dei parametri prima di inviare il segnale di conferma per stabilire la comunicazione; nel frattempo, lo stato del peer è PENDING.
È proprio qui che sopraggiunge la vulnerabilità: all’arrivo di una richiesta di configurazione, la funzione l2cap_parse_conf_rsp
riceve in input un buffer ( void *rsp
) e la sua grandezza ( int len
); scompone quindi il contenuto del pacchetto, lo valida e ricompone il pacchetto di risposta.
La dimensione del buffer di risposta, però, non è specificata nella funzione. Il contenuto del pacchetto, inoltre, può contenere dati duplicati e concede all’attaccante di manipolare a proprio piacimento sia la dimensione del buffer che i dati contenuti.
La funzione, invocata da l2cap_config_rsp
quando il dispositivo è nello stato PENDING
, può essere triggerata inviando una richiesta in cui il campo stype
assume il valore L2CAP_SERV_NOTRAFIC
, in modo da sostituire il buffer buf
allocato con dimensione 64 con uno arbitrario e portare a termine il buffer overflow.
I ricercatori fanno notare come molto spesso una vulnerabilità del genere non porti immediatamente a una remote code execution, in quanto possono essere adottate misure di sicurezza nei confronti del codice come le “variabili canarino” (che, se abilitate, vengono posizionate appena fuori della porzione di memoria da proteggere e hanno il ruolo di segnalare eventuali riscritture fuori dal buffer protetto) e la randomizzazione del kernel space (KASLR); questo, però, non viene spesso applicato soprattutto in dispositivi con quantitativi di memoria limitati.
L’impatto della vulnerabilità, inoltre, è alto poiché il codice iniettato viene eseguito direttamente in kernel-space.
Di seguito un video illustrativo dell’attacco:
CVE-2017-1000250
Tale vulnerabilità consiste in un possibile leak di informazioni su BlueZ dato da una lettura out-of-bound nell’implementazione, questa volta, del protocollo SDP.
SDP, come precedentemente anticipato, è il componente per la discovery dei servizi offerti dai dispositivi bluetooth nelle vicinanze, censiti tramite un meccanismo basato su identificatori univoci sulla base della tipologia di servizio. Anche tale meccanismo è basato su un approccio domanda-risposta; inoltre definisce un metodo di frammentazione proprietario, denominato nella specifica protocollare “SDP continuation”, che, qualora il messaggio inviato risultasse di dimensione eccedente rispetto all’MTU negoziato dal sottostante L2CAP, duplica il messaggio appendendovi un tag denominato “continuation state”, il cui valore è contenuto nel frammento di risposta ottenuto inizialmente.
Non è ben chiaro perché sia stato implementato un simile metodo di frammentazione, ulteriore alla segmentazione di L2CAP, sta di certo che la sua implementazione in BlueZ presenta qualche problema.
Nel demone bluetoothd di bluez (eseguito in userspace), è presente un errore nella validazione del campo maxByteSent
del continuation state (che l’utente può tranquillamente manipolare) che può causare un buffer overflow nell’esecuzione della funzione memcpy, fornendo la possibilità all’utente di leggere dati dallo stack analogamente a quanto accade per l’exploit Heartbleed di SSL.
CVE-2017-0785
Tale vulnerabilità è analoga alla precedente – ancora una volta sull’implementazione di SDP – tuttavia il bug è di natura diversa. Nell’SDP server di Android, la CVE-2017-1000250 non è sfruttabile, a causa del fatto che la frammentazione è implementata in maniera leggermente diversa: è presente un campo cont_offset
che contiene l’offset del record SDP inviato per ultimo nel pacchetto.
All’interno del codice, questo valore viene sottratto al numero di record SDP totali ( num_rsp_handles
), per determinare quelli rimanenti da trasferire, memorizzati in rem_handler
, di tipo uint16
.
Il valore num_rsp_handles
è ovviamente determinato per ogni ricerca, ma a differenza di cont_offset
è dichiarato fuori dallo scope della funzione e rimane sempre lo stesso durante la lettura dei vari frammenti. L’implementazione ha come presupposto, quindi, che sia num_response_handles
e cont_offset
siano riferiti alla stessa risposta effettivamente inviata.
Un attaccante può pertanto creare una situazione di confusione effettuando una ricerca SDP su un servizio, nella risposta (la cui dimensione sarà pari all’MTU della connessione, negoziato su decisione dell’attaccante stesso) otterrà un continuation state che allegherà in una successiva scansione SDP su un servizio differente, la cui risposta sarà di dimensione inferiore.
A questo punto rem_handles
, di tipo unsigned, assumerà un valore negativo e andrà in underflow assumendo un valore molto alto se considerato in complemento a due.
Il ciclo successivo, il cui compito è quello di copiare i record trovati nella risposta, avrà un numero di iterazioni molto elevato ed andrà a leggere (ed includere nella risposta stessa) porzioni di memoria fuori dal buffer.
CVE-2017-0781 e CVE-2017-0782
Trattasi entrambe di remote code execution su Android incluse nella gestione del protocollo BNEP (Bluetooth Network Encapsulation Protocol), utilizzato per costruire reti PAN (Personal Area Network) e consentire l’incapsulamento di pacchetti Ethernet in L2CAP.
BNEP supporta sia il trasporto di frame Ethernet (MTU di 1500 bytes) che il trasporto di messaggi di controllo, utili a negoziare la creazione della PAN e alla gestione dei flussi. È possibile includere più messaggi di controllo all’interno dello stesso pacchetto L2CAP, mediante l’utilizzo di “header estesi”. Entrambe le vulnerabilità in oggetto riguardano proprio questo aspetto.
La conseguenza della gestione di più header estesi in una volta sola, consiste nel fatto che la connessione può cambiare di stato tra la gestione di uno header e l’altro.
Alcuni di questi, tuttavia, possono essere trattati solo quando la connessione è in uno stato specifico; per gestire tale problematica gli sviluppatori di Android hanno deciso di tenere in memoria la parte del messaggio non ancora trattata per effettuarne il parsing nel momento opportuno, memorizzandola in p_pending_data
(tipo BT_HDR
, di dimensione 8 byte).
Tale campo è memorizzato nello heap, ed ha lunghezza rem_len
(che contiene la dimensione dei dati rimanenti del quale non è ancora stato effettuato il parsing, ed il valore può essere controllato dall’utente agendo sulla dimensione del pacchetto inviato). Successivamente viene effettuato il memcpy
della zona di memoria partendo dall’indirizzo di p_pending_data+1
, utilizzando rem_len
come dimensione. Ciò dà luogo alla prima vulnerabilità: memcpy
corrompe lo heap ogni volta che il codice viene eseguito. Il buffer overflow può essere scatenato inviando un pacchetto così formato:
Il campo type è composto dal bit extension_present
, che assume valore 1, e dal tipo di frame segnato come BNEP_FRAME_CONTROL
(01). Il campo ctrl_type
è impostato a BNEP_SETUP_CONNECTION_REQUEST_MSG
, per raggiungere la porzione di codice vulnerabile. len
viene impostato a 0, per manipolare il campo rem_len
, mentre il campo Payload conterrà i byte da iniettare nel buffer.
La seconda vulnerabilità è di nuovo un underflow che risiede nella funzione bnep_process_control_packet
, il cui compito è quello di elaborare i pacchetti di controllo e gli header estesi, al fine di riconoscere eventuali sotto-messaggi del messaggio BNEP principale. L’intero rem_len
è definito, ancora una volta, come unsigned short a 16 bit.
Manipolando il valore di ext_len
(8 bit, unsigned), è possibile mandare in underflow rem_len
sfruttando il complemento a due così da fargli assumere valori sull’ordine di 0xff00
. Il valore di tale variabile verrà poi utilizzato per assegnare la grandezza al buffer p_buf
( pbuf->size
), che verrà passato ai layer protocollari sottostanti. Questi si troveranno a gestire un buffer esageratamente grande, che non verrà più controllato e sarà passato alla funzione memcpy
così com’è. Il contenuto effettivamente copiato con memcpy
non è sotto il controllo dell’attaccante, ma è possibile, in tal caso, realizzare un attacco di tipo heap spray.
Per scatenare l’attacco è possibile inviare un pacchetto così formato:
Il campo type indica BNEP_FRAME_COMPRESSED_ETHERNET
, con flag extension_present
settato.
ext_len
contiene il valore controllato dall’attaccante per causare l’underflow della variabile rem_len
. control_type
ha valore 0x10
per raggiungere la porzione di codice vulnerabile. Raggiungendo l’underflow, rem_len
verrà copiata in pbuf->size
che, passato al layer sottostante, chiamerà la callback che eseguirà la memcpy
.
Entrambe le vulnerabilità possono causare l’esecuzione di codice remoto, con i privilegi del servizio Bluetooth ( com.android.bluetooth
).
Tale servizio ha privilegi di accesso al filesystem e controllo completo dello stack di rete a basso livello, può simulare input ed è gestito dal demone Zygote che, anche in caso di crash, ne ripristina l’esecuzione; questo concede all’attaccante di effettuare infiniti tentativi di intrusione.
CVE-2017-0783 e CVE-2017-8628 Bluetooth Pineapple Logical Flaw (Android e Windows)
Tali vulnerabilità consentono di effettuare attacchi man-in-the-middle . La prima, per Android, riguarda le versioni del sistema operativo compilate prima del 9 settembre: Google ha infatti rilasciato la patch per tali vulnerabilità nello scorso security bulletin. La seconda, per Windows, riguarda tutte le versioni del sistema di Redmond comprese tra Windows Vista e Windows 10. Curioso, in tal senso, è il fatto che la stessa tipologia di vulnerabilità sia presente su due sistemi operativi che non hanno nulla in comune; si tratta infatti di un difetto di design dovuto dalla complessità dello stack protocollare, che ha portato gli sviluppatori a seguire fedelmente le specifiche.
In particolare è stata rilevata un’incorretta gestione dei livelli di sicurezza richiesti dal profilo PAN, utilizzato per la costruzione di Personal Area Network così da permettere al protocollo Bluetooth di offrire alcuni servizi di rete come il tethering della connessione Internet.
#define PAN_SECURITY (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT)
Il livello di sicurezza richiesto è soddisfatto anche solo con BTM_SEC_IN_AUTHENTICATE
attivo, senza effettuare autorizzazioni successive.
Gli attacchi sono basati sull’assunzione che l’autenticazione Bluetooth, effettuata tramite il protocollo SMP (Security Manager Protocol) siano facilmente bypassabili. L’attaccante può quindi accedere a profili e servizi per i quali il livello di sicurezza richiede esplicitamente l’autenticazione con uno sforzo piuttosto minimo (specialmente su Android, sfruttando la funzionalità “It Just Works”).
Passando i parametri di autenticazione, l’attaccante è in grado di attivare una connessione BNEP ed avviare una connessione PAN dichiarando i ruoli di entrambi i peer. Egli assumerà il ruolo PANU, il ricevente NAP; tuttavia, nel momento in cui il dispositivo ricevente si accorgerà di non poter offrire la funzionalità di tethering, la connessione verrà interrotta. Poiché, tuttavia, i ruoli sono decisi da chi inizia la connessione, possono essere effettuati vari tentativi come illustrato nella seguente matrice:
Invertendo i ruoli, l’attaccante può assumere il ruolo NAP e il ricevente PANU, così da mandare a buon fine la connessione; la vittima sarà quindi in rete con l’attaccante, il quale potrà inviare configurazioni di rete malevole tramite il protocollo DHCP.
Tale attacco è di facile attuazione ed ha un potenziale molto elevato e, soprattutto, non richiede interazione con la vittima. Esso è assimilabile al WiFi Pineapple, perpetrabile soltanto nel caso in cui la vittima sia connessa ad una rete WiFi aperta.
Di seguito il video dell’attacco Pineapple su Windows:
CVE-2017-14315
Questa vulnerabilità riguarda il mondo Apple, coprendo le versioni di iOS precedenti alla 10 e di Apple TV OS precedenti alla 7.2.2. Il protocollo interessato è il “Low Energy Audio Protocol” (LEAP), realizzato da Apple per interconnettere gli auricolari e l’apparato Siri Remote tramite la funzionalità Low Energy introdotta con la versione 4 delle specifiche protocollari Bluetooth.
Nonostante il protocollo sia destinato al solo uso da parte di dispositivi audio di tipo low energy, è di fatto utilizzabile anche con dispositivi classici. Per funzionare, LEAP utilizza 2 specifici Channel ID: 0x2A per le operazioni di controllo della comunicazione e 0x2B per il flusso audio. Le operazioni di validazione controllano soltanto questi due parametri, inoltre i meccanismi di sicurezza di L2CAP non sono supportati, e il traffico dati non è autenticato. I pacchetti audio vengono gestiti da una callback (audio_handler_callback) nella quale è invocata la funzione memcpy
senza controllare la dimensione del buffer, provocando un possibile buffer overflow.
Secondo gli esperti di Armis, tale vulnerabilità deriva dall’assunzione che i pacchetti siano sempre grandi 0x68 bytes, come da specifica protocollare; situazione che si verifica sicuramente per le connessioni BLE ma non per le connessioni classiche.
La vulnerabilità non risulta però presente per le versioni attuali dei sistemi operativi di Cupertino, pertanto rimane valida solo per i dispositivi non ancora aggiornati almeno ad iOS 10.
In conclusione
BlueBorne arriva come ennesimo set di vulnerabilità Bluetooth; prima del rilascio delle specifiche protocollari della versione 2.1, infatti, molte erano le problematiche di sicurezza di tale standard dovute a difetti di progettazione. Nessuna di queste, tuttavia, aveva mai riguardato la possibilità di eseguire codice arbitrario.
Armis ha segnalato le vulnerabilità ai principali produttori e alla comunità Linux. Microsoft, avvisata ad aprile, ha rilasciato i propri aggiornamenti lo scorso luglio; i sistemi operativi aggiornati dopo tale data, hanno pertanto già percepito la patch. Apple è stata avvisata solamente ad agosto, le vulnerabilità non sono presenti nelle versioni attuali di iOS ed Apple TV. Samsung è stata contattata diverse volte, ma non ha mai risposto alla chiamata; diverso invece il feedback da parte di Google e della comunità Linux: la patch per Android è arrivata da Mountain View nel security bulletin di settembre, per quanto riguarda il kernel Linux, invece, la segnalazione della vulnerabilità è stata ricevuta dal team di sicurezza il 5 settembre e i manutentori delle varie distribuzioni stanno rilasciando gli aggiornamenti dal 12 settembre (si veda ad esempio il bollettino di Red Hat ).
Su Android, gli utenti possono eseguire questo scanner per verificare la presenza della vulnerabilità sul proprio dispositivo.
È buona pratica, pertanto, tenere i software costantemente aggiornati ma, come noto, ciò non sempre può corrispondere alla realtà dei fatti: per ragioni di obsolescenza programmata, difficoltà di erogazione degli aggiornamenti su determinate categorie di dispositivi, device che hanno raggiunto la end-of-life , inadempienza degli utenti, rimarranno numerosi i dispositivi “in-the-wild” che non riceveranno mai una patch. Per tali dispositivi occorre rinunciare alle funzionalità Bluetooth, almeno quando non strettamente necessarie.
Patrizio Tufarolo