Milioni di binari dopo. Come Linux è diventato più forte

Milioni di binari dopo. Come Linux è diventato più forteTL; DR. In questo articolo esploriamo gli schemi di rafforzamento che funzionano immediatamente su cinque popolari distribuzioni Linux. Per ciascuno, abbiamo preso la configurazione predefinita del kernel, caricato tutti i pacchetti e analizzato gli schemi di sicurezza nei file binari allegati. Le distribuzioni prese in considerazione sono OpenSUSE 12.4, Debian 9, CentOS, RHEL 6.10 e 7, nonché Ubuntu 14.04, 12.04 e 18.04 LTS.

I risultati confermano che anche gli schemi di base come l’impilamento dei canarini e il codice indipendente dalla posizione non sono ancora adottati da tutti. La situazione è ancora peggiore per i compilatori quando si tratta di proteggersi da vulnerabilità come lo stack crush, che è venuto alla ribalta a gennaio dopo la pubblicazione informazioni sulle vulnerabilità del sistema. Ma non tutto è così disperato. Un numero significativo di file binari implementa metodi di protezione di base e il loro numero cresce da versione a versione.

La revisione ha mostrato che il maggior numero di metodi di protezione è implementato in Ubuntu 18.04 a livello di sistema operativo e di applicazione, seguito da Debian 9. D'altra parte, OpenSUSE 12.4, CentOS 7 e RHEL 7 implementano anche schemi di protezione di base e protezione dalle collisioni dello stack viene utilizzato ancora più ampiamente con un insieme molto più denso di pacchetti predefiniti.

Introduzione

È difficile garantire un software di alta qualità. Nonostante il vasto numero di strumenti avanzati per l’analisi statica del codice e l’analisi dinamica del runtime, nonché i progressi significativi nello sviluppo di compilatori e linguaggi di programmazione, il software moderno soffre ancora di vulnerabilità che vengono costantemente sfruttate dagli aggressori. La situazione è ancora peggiore negli ecosistemi che includono codice legacy. In questi casi, non solo ci troviamo di fronte all’eterno problema di trovare possibili errori sfruttabili, ma siamo anche limitati da rigidi framework di compatibilità con le versioni precedenti, che spesso ci richiedono di preservare codice limitato o, peggio ancora, vulnerabile o pieno di bug.

È qui che entrano in gioco i metodi per proteggere o rafforzare i programmi. Non possiamo prevenire alcune tipologie di errori, ma possiamo rendere la vita più difficile all’aggressore e risolvere parzialmente il problema prevenendo o impedendo Operativo questi errori. Tale protezione viene utilizzata in tutti i moderni sistemi operativi, ma i metodi differiscono notevolmente per complessità, efficienza e prestazioni: dagli stack canary e ASLR alla protezione completa CFI и POR. In questo articolo vedremo quali metodi di protezione vengono utilizzati nelle distribuzioni Linux più popolari nella configurazione predefinita ed esamineremo anche le proprietà dei file binari distribuiti attraverso i sistemi di gestione dei pacchetti di ciascuna distribuzione.

CVE e sicurezza

Abbiamo tutti visto articoli con titoli come "Le applicazioni più vulnerabili dell'anno" o "I sistemi operativi più vulnerabili". Di solito forniscono statistiche sul numero totale di record relativi a vulnerabilità come CVE (vulnerabilità ed esposizioni comuni), ottenuto da Database nazionale delle vulnerabilità (NVD) от NIST e altre fonti. Successivamente, queste applicazioni o sistemi operativi vengono classificati in base al numero di CVE. Sfortunatamente, sebbene i CVE siano molto utili per tenere traccia dei problemi e informare fornitori e utenti, dicono poco sull’effettiva sicurezza del software.

Ad esempio, consideriamo il numero totale di CVE negli ultimi quattro anni per il kernel Linux e le cinque distribuzioni server più popolari, vale a dire Ubuntu, Debian, Red Hat Enterprise Linux e OpenSUSE.

Milioni di binari dopo. Come Linux è diventato più forte
Fig. 1

Cosa ci dice questo grafico? Un numero maggiore di CVE significa che una distribuzione è più vulnerabile di un’altra? Nessuna risposta. Ad esempio, in questo articolo vedrai che Debian ha meccanismi di sicurezza più forti rispetto, ad esempio, a OpenSUSE o RedHat Linux, e tuttavia Debian ha più CVE. Tuttavia, non significano necessariamente un indebolimento della sicurezza: anche la presenza di un CVE non indica se lo sia o meno una vulnerabilità sfruttati. I punteggi di gravità forniscono un’indicazione su come вероятно sfruttamento di una vulnerabilità, ma in definitiva la sfruttabilità dipende fortemente dalle protezioni presenti nei sistemi interessati e dalle risorse e capacità degli aggressori. Inoltre, l'assenza di rapporti CVE non dice nulla sugli altri non registrato o sconosciuto vulnerabilità. La differenza nel CVE può essere dovuta a fattori diversi dalla qualità del software, comprese le risorse destinate ai test o alla dimensione della base utenti. Nel nostro esempio, il numero più elevato di CVE di Debian potrebbe semplicemente indicare che Debian fornisce più pacchetti software.

Naturalmente il sistema CVE fornisce informazioni utili che permettono di creare opportune protezioni. Quanto meglio comprendiamo le ragioni del fallimento del programma, tanto più facile sarà identificare possibili metodi di sfruttamento e sviluppare meccanismi adeguati rilevamento e risposta. Nella fig. 2 mostra le categorie di vulnerabilità per tutte le distribuzioni negli ultimi quattro anni (fonte). È subito chiaro che la maggior parte dei CVE rientra nelle seguenti categorie: negazione del servizio (DoS), esecuzione di codice, overflow, danneggiamento della memoria, perdita di informazioni (esfiltrazione) ed escalation dei privilegi. Sebbene molti CVE vengano conteggiati più volte in diverse categorie, in generale gli stessi problemi persistono anno dopo anno. Nella parte successiva dell'articolo valuteremo l'utilizzo di vari schemi di protezione per prevenire lo sfruttamento di queste vulnerabilità.

Milioni di binari dopo. Come Linux è diventato più forte
Fig. 2

compiti

In questo articolo intendiamo rispondere alle seguenti domande:

  • Qual è la sicurezza delle diverse distribuzioni Linux? Quali meccanismi di protezione esistono nel kernel e nelle applicazioni dello spazio utente?
  • Come è cambiata nel tempo l’adozione dei meccanismi di sicurezza nelle diverse distribuzioni?
  • Quali sono le dipendenze medie di pacchetti e librerie per ciascuna distribuzione?
  • Quali protezioni sono implementate per ciascun binario?

Selezione delle distribuzioni

Risulta difficile trovare statistiche accurate sulle installazioni di distribuzione, poiché nella maggior parte dei casi il numero di download non indica il numero di installazioni effettive. Tuttavia, le varianti Unix costituiscono la maggior parte dei sistemi server (sui server web il 69,2%, di statistica W3techs e altre fonti) e la loro quota è in costante crescita. Pertanto, per la nostra ricerca ci siamo concentrati sulle distribuzioni disponibili immediatamente sulla piattaforma Google cloud. In particolare abbiamo selezionato il seguente sistema operativo:

Distribuzione/versione
nucleo
Costruire

OpenSUSE 12.4
4.12.14-95.3-predefinito
#1 SMP mercoledì 5 dicembre 06:00:48 UTC 2018 (63a8d29)

Debian 9 (allungato)
4.9.0-8-amd64
#1 SMP Debian 4.9.130-2 (2018-10-27)

6.10 CentOS
2.6.32-754.10.1.el6.x86_64
#1 SMP martedì 15 gennaio 17:07:28 UTC 2019

7 CentOS
3.10.0-957.5.1.el7.x86_64
#1 SMP venerdì 1 febbraio 14:54:57 UTC 2019

Red Hat Enterprise Linux Server 6.10 (Santiago)
2.6.32-754.9.1.el6.x86_64
#1 SMP mercoledì 21 novembre 15:08:21 EST 2018

Red Hat Enterprise Linux Server 7.6 (Maipo)
3.10.0-957.1.3.el7.x86_64
#1 SMP giovedì 15 novembre 17:36:42 UTC 2018

Ubuntu 14.04 (affidabile Tahr)
4.4.0–140-generico

#166~14.04.1-Ubuntu SMP sabato 17 novembre 01:52:43 UTC 20...

Ubuntu 16.04 (Xenial Xerus)
4.15.0–1026-gcp
#27~16.04.1-Ubuntu SMP venerdì 7 dicembre 09:59:47 UTC 2018

Ubuntu 18.04 (Castoro bionico)
4.15.0–1026-gcp
#27-Ubuntu SMP giovedì 6 dicembre 18:27:01 UTC 2018

Tabella 1

analisi

Studiamo la configurazione predefinita del kernel, nonché le proprietà dei pacchetti disponibili tramite il gestore pacchetti di ciascuna distribuzione pronta all'uso. Pertanto, consideriamo solo i pacchetti provenienti dai mirror predefiniti di ciascuna distribuzione, ignorando i pacchetti provenienti da repository instabili (come i mirror 'testing' di Debian) e i pacchetti di terze parti (come i pacchetti Nvidia dai mirror standard). Inoltre, non consideriamo compilazioni di kernel personalizzate o configurazioni con maggiore sicurezza.

Analisi della configurazione del kernel

Abbiamo applicato uno script di analisi basato su controllo kconfig gratuito. Diamo un'occhiata ai parametri di protezione predefiniti delle distribuzioni denominate e confrontiamoli con l'elenco da Progetto fondamentale di autodifesa (KSPP). Per ciascuna opzione di configurazione, la Tabella 2 descrive l'impostazione desiderata: la casella di controllo è per le distribuzioni conformi alle raccomandazioni KSSP (vedere quanto segue per una spiegazione dei termini). qui; Nei prossimi articoli spiegheremo quanti di questi metodi di sicurezza sono nati e come hackerare un sistema in loro assenza).

Milioni di binari dopo. Come Linux è diventato più forte

Milioni di binari dopo. Come Linux è diventato più forte

In generale, i nuovi kernel hanno impostazioni più rigorose già pronte. Ad esempio, CentOS 6.10 e RHEL 6.10 sul kernel 2.6.32 mancano della maggior parte delle funzionalità critiche implementate nei kernel più recenti come SMAP, autorizzazioni RWX rigorose, randomizzazione degli indirizzi o protezione copy2usr. Va notato che molte delle opzioni di configurazione nella tabella non sono disponibili nelle versioni precedenti del kernel e non sono applicabili nella realtà - ciò viene comunque indicato nella tabella come mancanza di una protezione adeguata. Allo stesso modo, se un'opzione di configurazione non è presente in una determinata versione e la sicurezza richiede che tale opzione sia disabilitata, questa è considerata una configurazione ragionevole.

Altro punto da considerare nell’interpretazione dei risultati: alcune configurazioni del kernel che aumentano la superficie di attacco possono essere utilizzate anche per la sicurezza. Tali esempi includono uprobes e kprobes, moduli del kernel e BPF/eBPF. La nostra raccomandazione è di utilizzare i meccanismi di cui sopra per fornire una protezione reale, poiché non sono banali da utilizzare e il loro sfruttamento presuppone che gli attori malintenzionati abbiano già stabilito un punto d’appoggio nel sistema. Ma se queste opzioni sono abilitate, l'amministratore di sistema deve monitorare attivamente eventuali abusi.

Analizzando ulteriormente le voci nella Tabella 2, vediamo che i kernel moderni forniscono diverse opzioni per la protezione dallo sfruttamento di vulnerabilità come la fuga di informazioni e gli stack/heap overflow. Notiamo però che anche le distribuzioni più recenti e popolari non hanno ancora implementato protezioni più complesse (ad esempio con patch grsicurezza) o protezione moderna contro gli attacchi di riutilizzo del codice (ad es. combinazione di randomizzazione con schemi come R^X per il codice). A peggiorare le cose, anche queste difese più avanzate non proteggono dall’intera gamma di attacchi. Pertanto, è fondamentale per gli amministratori di sistema integrare le configurazioni intelligenti con soluzioni che offrano rilevamento e prevenzione degli exploit in fase di esecuzione.

Analisi delle applicazioni

Non sorprende che distribuzioni diverse abbiano caratteristiche dei pacchetti, opzioni di compilazione, dipendenze delle librerie, ecc. diverse. Esistono differenze anche per relazionato distribuzioni e pacchetti con un numero limitato di dipendenze (ad esempio coreutils su Ubuntu o Debian). Per valutare le differenze, abbiamo scaricato tutti i pacchetti disponibili, estratto il loro contenuto e analizzato i file binari e le dipendenze. Per ogni pacchetto abbiamo tenuto traccia degli altri pacchetti da cui dipende e per ogni binario abbiamo tracciato le sue dipendenze. In questa sezione riassumiamo brevemente le conclusioni.

distribuzioni

In totale, abbiamo scaricato 361 pacchetti per tutte le distribuzioni, estraendo solo pacchetti dai mirror predefiniti. Abbiamo ignorato i pacchetti senza eseguibili ELF, come sorgenti, caratteri, ecc. Dopo il filtraggio, sono rimasti 556 pacchetti, contenenti un totale di 129 binari. La distribuzione di pacchetti e file attraverso le distribuzioni è mostrata in Fig. 569.

Milioni di binari dopo. Come Linux è diventato più forte
Fig. 3

Potresti notare che più moderna è la distribuzione, più pacchetti e binari contiene, il che è logico. Tuttavia, i pacchetti Ubuntu e Debian includono molti più binari (sia eseguibili che moduli e librerie dinamici) rispetto a CentOS, SUSE e RHEL, il che potenzialmente influisce sulla superficie di attacco di Ubuntu e Debian (va notato che i numeri riflettono tutti i binari di tutte le versioni pacchetto, ovvero alcuni file vengono analizzati più volte). Ciò è particolarmente importante quando si considerano le dipendenze tra i pacchetti. Pertanto, una vulnerabilità in un singolo pacchetto binario può colpire molte parti dell'ecosistema, proprio come una libreria vulnerabile può colpire tutti i binari che la importano. Come punto di partenza, diamo un'occhiata alla distribuzione del numero di dipendenze tra i pacchetti in diversi sistemi operativi:

Milioni di binari dopo. Come Linux è diventato più forte
Fig. 4

In quasi tutte le distribuzioni, il 60% dei pacchetti ha almeno 10 dipendenze. Inoltre, alcuni pacchetti hanno un numero di dipendenze notevolmente maggiore (più di 100). Lo stesso vale per le dipendenze inverse dei pacchetti: come previsto, alcuni pacchetti vengono utilizzati da molti altri pacchetti nella distribuzione, quindi le vulnerabilità in quei pochi pacchetti selezionati sono ad alto rischio. A titolo di esempio, la tabella seguente elenca i 20 pacchetti con il numero massimo di dipendenze inverse in SLES, Centos 7, Debian 9 e Ubuntu 18.04 (ogni cella indica il pacchetto e il numero di dipendenze inverse).

Milioni di binari dopo. Come Linux è diventato più forte
Tabella 3

Fatto interessante. Sebbene tutti i sistemi operativi analizzati siano realizzati per l'architettura x86_64 e la maggior parte dei pacchetti abbia l'architettura definita come x86_64 e x86, i pacchetti spesso contengono file binari per altre architetture, come illustrato nella Figura 5. XNUMX.

Milioni di binari dopo. Come Linux è diventato più forte
Fig. 5

Nella prossima sezione approfondiremo le caratteristiche dei binari analizzati.

Statistiche sulla protezione dei file binari

Come minimo, devi esplorare un set di base di opzioni di sicurezza per i tuoi file binari esistenti. Diverse distribuzioni Linux sono dotate di script che eseguono tali controlli. Ad esempio, Debian/Ubuntu ha uno script di questo tipo. Ecco un esempio del suo lavoro:

$ hardening-check $(which docker)
/usr/bin/docker:
 Position Independent Executable: yes
 Stack protected: yes
 Fortify Source functions: no, only unprotected functions found!
 Read-only relocations: yes
 Immediate binding: yes

Lo script ne controlla cinque funzioni di protezione:

  • Position Independent Executable (PIE): indica se la sezione di testo di un programma può essere spostata in memoria per ottenere la randomizzazione se ASLR è abilitato nel kernel.
  • Stack protetto: indica se i canary stack sono abilitati per la protezione dagli attacchi di collisione dello stack.
  • Fortifica origine: se le funzioni non sicure (ad esempio, strcpy) vengono sostituite con le loro controparti più sicure e le chiamate controllate in fase di esecuzione vengono sostituite con le loro controparti non controllate (ad esempio, memcpy invece di __memcpy_chk).
  • Rilocazioni di sola lettura (RELRO): indica se le voci della tabella di rilocazione sono contrassegnate di sola lettura se vengono attivate prima dell'inizio dell'esecuzione.
  • Associazione immediata: indica se il linker di runtime consente tutti gli spostamenti prima dell'inizio dell'esecuzione del programma (questo equivale a un RELRO completo).

I meccanismi di cui sopra sono sufficienti? Sfortunatamente no. Esistono modi noti per aggirare tutte le difese di cui sopra, ma più dura è la difesa, maggiore è il livello per l'attaccante. Per esempio, Metodi di bypass RELRO più difficile da applicare se sono in vigore il PIE e il legame immediato. Allo stesso modo, l’ASLR completo richiede lavoro aggiuntivo per creare un exploit funzionante. Tuttavia, gli aggressori sofisticati sono già pronti a soddisfare tali protezioni: la loro assenza accelererà sostanzialmente l’hacking. È quindi essenziale che tali misure siano considerate necessarie minimo.

Volevamo studiare quanti file binari nelle distribuzioni in questione sono protetti da questi e altri tre metodi:

  • Bit non eseguibile (NX) impedisce l'esecuzione in qualsiasi regione che non dovrebbe essere eseguibile, come lo stack heap, ecc.
  • PERCORSO/PERCORSO denota il percorso di esecuzione utilizzato dal caricatore dinamico per trovare le librerie corrispondenti. Il primo è obbligatorio per qualsiasi sistema moderno: la sua assenza consente agli aggressori di scrivere arbitrariamente il carico utile in memoria ed eseguirlo così com'è. Per quanto riguarda il secondo, configurazioni errate del percorso di esecuzione aiutano a introdurre codice inaffidabile che può portare a una serie di problemi (ad es. aumento dei privilegie altri problemi).
  • La protezione dalle collisioni dello stack fornisce protezione contro gli attacchi che causano la sovrapposizione dello stack ad altre aree della memoria (come l'heap). Considerati i recenti exploit abusivi Vulnerabilità di collisione dell'heap systemd, abbiamo ritenuto opportuno includere questo meccanismo nel nostro set di dati.

Quindi, senza ulteriori indugi, veniamo ai numeri. Le tabelle 4 e 5 contengono un riepilogo dell'analisi rispettivamente dei file eseguibili e delle librerie di varie distribuzioni.

  • Come puoi vedere, la protezione NX è implementata ovunque, con rare eccezioni. In particolare si nota il suo utilizzo leggermente inferiore nelle distribuzioni Ubuntu e Debian rispetto a CentOS, RHEL e OpenSUSE.
  • I canary stack mancano in molti posti, specialmente nelle distribuzioni con kernel più vecchi. Si notano alcuni progressi nelle ultime distribuzioni di Centos, RHEL, Debian e Ubuntu.
  • Ad eccezione di Debian e Ubuntu 18.04, la maggior parte delle distribuzioni ha uno scarso supporto PIE.
  • La protezione dalle collisioni dello stack è debole in OpenSUSE, Centos 7 e RHEL 7 e praticamente inesistente in altri.
  • Tutte le distribuzioni con kernel moderni hanno un certo supporto per RELRO, con Ubuntu 18.04 in testa e Debian al secondo posto.

Come già accennato, i parametri in questa tabella rappresentano la media per tutte le versioni del file binario. Se guardi solo le ultime versioni dei file, i numeri saranno diversi (ad esempio, vedi Debian progredisce con l'implementazione PIE). Inoltre, la maggior parte delle distribuzioni in genere testa solo la sicurezza di alcune funzioni nel binario durante il calcolo delle statistiche, ma la nostra analisi mostra la reale percentuale di funzioni che sono rafforzate. Pertanto, se 5 funzioni su 50 sono protette in un binario, gli daremo un punteggio di 0,1, che corrisponde al 10% delle funzioni da potenziare.

Milioni di binari dopo. Come Linux è diventato più forte
Tabella 4. Caratteristiche di sicurezza per i file eseguibili mostrati in Fig. 3 (implementazione delle funzioni rilevanti come percentuale del numero totale di file eseguibili)

Milioni di binari dopo. Come Linux è diventato più forte
Tabella 5. Caratteristiche di sicurezza per le librerie mostrate in Fig. 3 (implementazione delle funzioni rilevanti in percentuale sul totale delle biblioteche)

Quindi ci sono progressi? Certamente sì: lo si evince dalle statistiche relative alle singole distribuzioni (ad es. Debian), nonché dalle tabelle precedenti. Come esempio in Fig. La Figura 6 mostra l'implementazione dei meccanismi di protezione in tre distribuzioni successive di Ubuntu LTS 5 (abbiamo omesso le statistiche sulla protezione dalle collisioni dello stack). Notiamo che da una versione all'altra sempre più file supportano gli stack canary, e anche sempre più binari vengono forniti con la protezione RELRO completa.

Milioni di binari dopo. Come Linux è diventato più forte
Fig. 6

Sfortunatamente, numerosi file eseguibili in diverse distribuzioni non dispongono ancora di nessuna delle protezioni di cui sopra. Ad esempio, guardando Ubuntu 18.04, noterai il binario ngetty (un sostituto di getty), così come le shell mksh e lksh, l'interprete picolisp, i pacchetti nvidia-cuda-toolkit (un pacchetto popolare per applicazioni accelerate da GPU come i framework di machine learning) e klibc -utils. Allo stesso modo, il binario mandos-client (uno strumento amministrativo che consente di riavviare automaticamente le macchine con file system crittografati) così come rsh-redone-client (una reimplementazione di rsh e rlogin) vengono forniti senza protezione NX, sebbene dispongano dei diritti SUID: (. Inoltre, diversi binari suid mancano della protezione di base come i canarini dello stack (ad esempio, il binario Xorg.wrap dal pacchetto Xorg).

Riepilogo e osservazioni conclusive

In questo articolo, abbiamo evidenziato diverse funzionalità di sicurezza delle moderne distribuzioni Linux. L'analisi ha mostrato che l'ultima distribuzione Ubuntu LTS (18.04) implementa, in media, la protezione a livello di sistema operativo e applicazione più potente tra le distribuzioni con kernel relativamente nuovi, come Ubuntu 14.04, 12.04 e Debian 9. Tuttavia, le distribuzioni esaminate CentOS, RHEL e OpenSUSE nel nostro set per impostazione predefinita producono un insieme più denso di pacchetti e nelle ultime versioni (CentOS e RHEL) hanno una percentuale più elevata di protezione dalle collisioni dello stack rispetto ai concorrenti basati su Debian (Debian e Ubuntu). Confrontando le versioni CentOS e RedHat, notiamo grandi miglioramenti nell'implementazione degli stack canary e RELRO dalle versioni dalla 6 alla 7, ma in media CentOS ha più funzionalità implementate rispetto a RHEL. In generale, tutte le distribuzioni dovrebbero prestare particolare attenzione alla protezione PIE che, ad eccezione di Debian 9 e Ubuntu 18.04, è implementata in meno del 10% dei file binari nel nostro set di dati.

Infine, va notato che sebbene abbiamo condotto la ricerca manualmente, sono disponibili molti strumenti di sicurezza (ad es. Lynis, Tigre, Hubble), che eseguono analisi e aiutano a evitare configurazioni non sicure. Sfortunatamente, anche una protezione forte in configurazioni ragionevoli non garantisce l'assenza di exploit. Ecco perché crediamo fermamente che sia fondamentale garantire monitoraggio affidabile e prevenzione degli attacchi in tempo reale, concentrandosi sui modelli di sfruttamento e prevenendoli.

Fonte: habr.com

Aggiungi un commento